opengl 矩阵/向量乘法阶数

drnojrws  于 2022-11-23  发布在  其他
关注(0)|答案(1)|浏览(173)

我在网上读过很多关于OpenGL中旋转、平移和缩放矩阵乘法的正确顺序的文章。然而,现在我开始自己实现它,我真的很困惑。
让我们假设在我的代码中,我正在计算变换矩阵,并将其作为一个结果矩阵传递给着色器:

shader.SetUniform("u_Matrix", scale * rotation * translation);

在顶点着色器中,我将顶点乘以这个矩阵:

gl_Position = u_Matrix * vec4(a_Position, 0.0, 1.0);

现在,按照这个顺序(缩放 * 旋转 * 平移),我得到的正是我想要的:我旋转对象,然后移动到特定的点,然后缩放它。有人能解释一下为什么这是正确的顺序吗?
我一直认为所有的变换都是“从矢量方面”应用的。
例如,如果我们“展开”乘法:

gl_Position = scale * rotation * translation * vec4(a_Position, 0.0, 1.0);

那么首先应该应用平移,然后是旋转和缩放。如果不是平移和旋转的顺序,我觉得一切都很好。如果我们不想围绕某个点旋转,我们应该先旋转,然后平移,这不是这里的情况。
为什么这种转换能按预期工作?

jrcvhitl

jrcvhitl1#

你的C++矩阵很可能是以行为主存储的,这意味着从左到右乘以它们是一个“原点”转换,而从右到左则是一个“局部”增量转换。
然而,OpenGL使用列主排序存储器布局(16元素阵列中的第13、第14和第15元素被视为平移分量)。
要在OpenGL中使用行主矩阵,可以执行以下两项操作:

  1. glUniformMatrix*()函数,有一个参数将GL_TRUE传递给transpose参数:
void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);

这会将它们重新排列为列主。
1.另一种方法是还原着色器中的操作顺序:

gl_Position = vec4(a_Position, 0.0, 1.0) * u_Matrix;

但是你会发现大多数GLSL文献将使用局部从左到右的列主排序,所以坚持这样做可能更好。
另一种选择是改变C++端的布局,使它们以列为主(但我个人认为行为主更容易处理)。

相关问题