【问题标题】:Matrix / vector multiplication order矩阵/向量乘法顺序
【发布时间】:2015-08-21 00:03:14
【问题描述】:

我在网上阅读了十几篇关于 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);

那么首先应该应用平移,然后是旋转和缩放。如果不是因为平移和旋转的顺序,一切对我来说似乎都很好。如果我们不想绕某个点旋转,我们应该先旋转然后平移,这里不是这样。

为什么这种转换会按预期进行?

【问题讨论】:

  • 当你说你已经阅读了几十篇文章时,有没有一篇文章涉及行矩阵和列矩阵以及前后乘法?您寻求的解释与这两件事有关,并且正确尝试解释为什么 OpenGL 的行为方式(列主要后乘法)应该包括它们。

标签: opengl math matrix vector


【解决方案1】:

您的 C++ 矩阵可能在引擎盖下存储为主要行。这意味着从左到右将它们相乘是“原点”转换,而从右到左将是“局部”增量转换。

然而,OpenGL 使用列主排序内存布局(16 元素数组中的第 13、14 和 15 个元素被视为平移组件)。

要在 OpenGL 中使用行主矩阵,您可以做 2 件事:

  1. glUniformMatrix* 函数,具有将 GL_TRUE 传递给转置的参数:

void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean转置, const GLfloat *value);

这会将它们重新排列为主要列。

  1. 另一个是在着色器中恢复操作的顺序:

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

但是您会发现大多数 GLSL 文献将使用本地从左到右列的主要排序,因此最好坚持使用它。

另一种选择是更改 C++ 端的布局,使它们成为列专业(但我个人认为行专业更容易处理)。

【讨论】:

  • 我现在明白了。 c++ 和着色器的转换顺序必须不同的原因是因为我对矩阵进行了多重处理,因为它们是行优先的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-29
  • 1970-01-01
  • 1970-01-01
  • 2020-03-16
  • 2020-01-17
  • 2016-01-23
相关资源
最近更新 更多