【问题标题】:Rotating/Translating Object In OpenGL在 OpenGL 中旋转/平移对象
【发布时间】:2020-11-12 19:32:04
【问题描述】:

我目前正在使用 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);

我真的不确定我不理解什么,我们将不胜感激。

编辑:我知道您可以更改顶点并重新绑定数组,但这似乎会很慢。这行得通吗?

【问题讨论】:

  • 如果你阅读这篇文章会很有帮助,它给出了OpenGL转换的详细解释。 learnopengl.com/Getting-started/Transformations
  • 好的,我查看了那篇文章,发现您可以使用 glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans)); 进行 GLSL 加载的转换,但我找不到使用 glm 向量并基于此进行转换的正确方法.

标签: c++ opengl glfw glm-math glad


【解决方案1】:

我假设您对不同坐标系和变换(如投影、视图和模型矩阵)的概念有些熟悉。如果没有,你应该在这里阅读它们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.

如果您需要有关此主题的更多信息,可以查看已回答的此线程

Using GLM's UnProject.


什么是 GLFW/GLAD 函数来改变相机的位置和旋转?

这只是视图矩阵。再看here


我基本上是在尝试创建 FPS 相机。我知道运动,但我不知道旋转。

您可以在此处查看 learnopengl.com/Getting-started/Camera。只需向下滚动,直到看到“环顾四周”部分。我认为那里的解释很好。


我已经看过了,但对一件事感到困惑。如果每个渲染的立方体都有视图、透视图和模型,我将如何更改相机的视图、透视图和模型?

好的,我想我理解这里的误解。并非所有 3 个矩阵都是每个对象。模型矩阵是每个对象,每个摄像机的视图矩阵和每个查看模式的投影矩阵(例如,90° 视角或正交的透视图),因此通常只有一次。

【讨论】:

  • 评论不适用于扩展讨论或调试会话;这个对话是moved to chat。请确保edit此答案包含所有相关信息。如果您有后续问题,请提出新问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-19
  • 2016-07-22
  • 1970-01-01
  • 2018-12-17
  • 2021-07-23
相关资源
最近更新 更多