Rotating/Translating OpenGL 中的对象
Rotating/Translating Object In OpenGL
我目前正在使用 OpenGL(Glad、GLFW、GLM)。我刚开始学习,找不到正确的方法来翻译并实际渲染它。例如,我想每帧旋转 1 度。我看过有关如何使用 GLM 进行这些翻译的教程,但我似乎无法弄清楚如何采用这样的方法:glm::mat4 translate = glm::translate(glm::mat4(1.f), glm::vec3(2.f, 0.f, 0.f));
并将其应用于这样呈现的对象:
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES,3, GL_UNSIGNED_INT, 0);
我真的不确定我不理解什么,我们将不胜感激。
编辑:我知道您可以只更改顶点并重新绑定数组,但这似乎很慢。那行得通吗?
我假设您对投影、视图和模型矩阵等不同坐标系和变换的概念有些熟悉。如果没有,您应该在这里 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
。
Edit: I know you can just change the vertices and rebind the array, but that seems like it would be pretty slow. Would that work?
如果您想更改模型的外观,您可以随时编辑模型。但是,CPU 上的转换速度会慢很多。请记住,GPU 针对此类任务进行了高度优化。所以我建议在 GPU 上进行大部分转换。
如果您只需要更改对象的一部分顶点,在大多数情况下更新顶点会更好。
How would I constantly rotate as a function of time?
要根据时间旋转,有多种方法。澄清一下,应用于着色器中对象的变换不是永久性的,将在下一次绘制调用时重置。如果使用同一轴执行旋转,最好在某处指定角度,然后计算该角度的单个旋转(矩阵)。要使用 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;
在这两种情况下,您都需要像我上面解释的那样为您的模型矩阵设置旋转。
Also, if I wanted to make a square follow the mouse, would I have to rebuild the vertices every time the mouse moves?
不,你不需要那样做。如果只想将方块移动到鼠标所在的位置,可以使用平移。要获取鼠标在世界space中的位置,似乎可以使用glm::unProject( ... );
。我还没有尝试过这个,但看起来它可以解决你的问题。你可以在这里看看
https://glm.g-truc.net/0.9.2/api/a00245.html#gac38d611231b15799a0c06c54ff1ede43.
如果您需要有关此主题的更多信息,可以查看已回答此问题的帖子
Using GLM's UnProject.
what's the GLFW/GLAD function to change the camera's position and rotation?
那只是视图矩阵。再看here
I'm basically trying to create the FPS camera. I figured out movement but I can't figure out rotation.
你可以看这里learnopengl.com/Getting-started/Camera。只需向下滚动,直到看到“环顾四周”部分。我觉得那里的解释很好
I already looked at that but was confused about one thing. If each rendered cube has view, perspective, and model, how would I change the camera's view, perspective, and model?
好的,我想我理解这里的误解。并非所有 3 个矩阵都是针对每个对象的。模型矩阵是每个对象,每个相机的视图矩阵和每个查看模式的投影矩阵(例如,视角为 90° 或正交的透视图)因此通常只有一次。
我目前正在使用 OpenGL(Glad、GLFW、GLM)。我刚开始学习,找不到正确的方法来翻译并实际渲染它。例如,我想每帧旋转 1 度。我看过有关如何使用 GLM 进行这些翻译的教程,但我似乎无法弄清楚如何采用这样的方法:glm::mat4 translate = glm::translate(glm::mat4(1.f), glm::vec3(2.f, 0.f, 0.f));
并将其应用于这样呈现的对象:
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES,3, GL_UNSIGNED_INT, 0);
我真的不确定我不理解什么,我们将不胜感激。
编辑:我知道您可以只更改顶点并重新绑定数组,但这似乎很慢。那行得通吗?
我假设您对投影、视图和模型矩阵等不同坐标系和变换的概念有些熟悉。如果没有,您应该在这里 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
。
Edit: I know you can just change the vertices and rebind the array, but that seems like it would be pretty slow. Would that work?
如果您想更改模型的外观,您可以随时编辑模型。但是,CPU 上的转换速度会慢很多。请记住,GPU 针对此类任务进行了高度优化。所以我建议在 GPU 上进行大部分转换。
如果您只需要更改对象的一部分顶点,在大多数情况下更新顶点会更好。
How would I constantly rotate as a function of time?
要根据时间旋转,有多种方法。澄清一下,应用于着色器中对象的变换不是永久性的,将在下一次绘制调用时重置。如果使用同一轴执行旋转,最好在某处指定角度,然后计算该角度的单个旋转(矩阵)。要使用 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;
在这两种情况下,您都需要像我上面解释的那样为您的模型矩阵设置旋转。
Also, if I wanted to make a square follow the mouse, would I have to rebuild the vertices every time the mouse moves?
不,你不需要那样做。如果只想将方块移动到鼠标所在的位置,可以使用平移。要获取鼠标在世界space中的位置,似乎可以使用glm::unProject( ... );
。我还没有尝试过这个,但看起来它可以解决你的问题。你可以在这里看看
https://glm.g-truc.net/0.9.2/api/a00245.html#gac38d611231b15799a0c06c54ff1ede43.
如果您需要有关此主题的更多信息,可以查看已回答此问题的帖子
Using GLM's UnProject.
what's the GLFW/GLAD function to change the camera's position and rotation?
那只是视图矩阵。再看here
I'm basically trying to create the FPS camera. I figured out movement but I can't figure out rotation.
你可以看这里learnopengl.com/Getting-started/Camera。只需向下滚动,直到看到“环顾四周”部分。我觉得那里的解释很好
I already looked at that but was confused about one thing. If each rendered cube has view, perspective, and model, how would I change the camera's view, perspective, and model?
好的,我想我理解这里的误解。并非所有 3 个矩阵都是针对每个对象的。模型矩阵是每个对象,每个相机的视图矩阵和每个查看模式的投影矩阵(例如,视角为 90° 或正交的透视图)因此通常只有一次。