我假设您对不同坐标系和变换(如投影、视图和模型矩阵)的概念有些熟悉。如果没有,您应该在此处阅读它们https://learnopengl.com/Getting-started/Coordinate-Systems。
简而言之,模型矩阵将世界中的对象作为一个整体进行变换。在大多数情况下,它包含平移、旋转和缩放。需要注意的是,矩阵乘法的阶数一般定义为
glm::mat4 model = translate * rotate * scale;
需要使用视图矩阵来获得相机的视图,而投影矩阵添加透视并用于确定屏幕上的内容以及将被渲染的内容。
要将变换应用于要使用着色器绘制的对象,您需要先将矩阵加载到着色器中。
glm::mat4 model = glm::translate(glm::mat4(1.f), glm::vec3(2.f, 0.f, 0.f));
unsigned int modelMatrixLoc = glGetUniformLocation(ourShader.ID, "model");
glUniformMatrix4fv(modelMatrixLoc , 1, GL_FALSE, glm::value_ptr(model));
在这里,模型矩阵将以“模型”的名称加载到着色器中。然后,您可以在着色器中使用此矩阵来转换 GPU 上的顶点。
一个简单的着色器看起来像这样
#version 460 core
layout (location = 0) in vec3 position_in;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(position_in, 1.0);
}
为确保您的法线向量不会倾斜,您可以计算另一个矩阵
glm::mat3 model_normal = glm::transpose(glm::inverse(model));
如果你要将它添加到着色器中,它看起来像这样
#version 460 core
layout (location = 0) in vec3 position_in;
layout (location = 1) in vec3 normal_in;
uniform mat4 model;
uniform mat3 model_normal;
uniform mat4 view;
uniform mat4 projection;
out vec3 normal;
void main()
{
gl_Position = projection * view * model * vec4(position_in, 1.0);
normal = model_normal * normal_in;
}
请注意我们现在如何使用 mat3 而不是 mat4?这是因为我们不想平移法线向量,而矩阵的平移部分位于第四列,我们在这里将其切除。这也意味着将 4d 向量的最后一个分量设置为1
是否要平移和0
不平移非常重要。
编辑:我知道您可以更改顶点并重新绑定数组,但这似乎会很慢。那行得通吗?
如果你想改变它的外观,你可以随时编辑你的模型。但是,转换在 CPU 上会慢很多。请记住,GPU 已针对此类任务进行了高度优化。所以我建议在 GPU 上进行大多数转换。
如果您只需要更改对象的部分顶点,则在大多数情况下更新顶点会更好。
我将如何随着时间不断地旋转?
作为时间的函数旋转,有多种方法。澄清一下,应用于着色器中对象的变换不是永久性的,将在下一次绘制调用时重置。如果使用同一轴执行旋转,最好在某处指定角度,然后为该角度计算单个旋转(矩阵)。要使用 GLFW 执行此操作,您可以使用
const double radians_per_second = ... ;
const glm::vec3 axis = ... ;
// rendering loop start
double time_seconds = glfwGetTime();
float angle = radians_per_second * time_seconds;
glm::mat4 rotation = glm::rotate(glm::mat4(1.f), angle, axis);
另一方面,如果旋转不在同一轴上执行,则必须将两个旋转矩阵相乘。
rotation = rotation * additional_rotation;
在这两种情况下,您都需要像我上面解释的那样为模型矩阵设置旋转。
另外,如果我想让一个正方形跟随鼠标,每次鼠标移动时我都必须重建顶点吗?
不,您不需要这样做。如果只想将方块移动到鼠标的位置,可以使用平移。要获得鼠标在世界空间中的位置,您似乎可以使用glm::unProject( ... );
. 我还没有尝试过,但看起来它可以解决你的问题。你可以看看这里
https://glm.g-truc.net/0.9.2/api/a00245.html#gac38d611231b15799a0c06c54ff1ede43。
如果您需要有关此主题的更多信息,可以查看已回答的此线程
使用 GLM 的 UnProject。
改变相机位置和旋转的 GLFW/GLAD 功能是什么?
那只是视图矩阵。再看这里。
我基本上是在尝试创建 FPS 相机。我想出了运动,但我不知道旋转。
你可以在这里看看 learnopengl.com/Getting-started/Camera。只需向下滚动,直到看到“环顾四周”部分。我认为那里的解释非常好。
我已经看过了,但对一件事感到困惑。如果每个渲染的立方体都有视图、透视和模型,我将如何更改相机的视图、透视和模型?
好的,我想我理解这里的误解。并非所有 3 个矩阵都是每个对象。模型矩阵是每个对象,每个相机的视图矩阵和每个查看模式的投影矩阵(例如,具有 90° 或正交视野的透视图),因此通常只有一次。