【问题标题】:Opengl order of matrix transformations矩阵变换的Opengl顺序
【发布时间】:2013-04-06 06:40:37
【问题描述】:

假设我有一个蓝色 3D 盒子(顶部为红色)。

  1. 现在我调用 glScalef(1, 10, 1)。
  2. 然后我调用 glRotatef(90, 0, 1, 0)。
  3. 然后我渲染立方体。

我期望看到红色的一面朝向屏幕并拉伸(沿模型的 Y 轴)。

但我看到的是这样的: 红色的一面朝向屏幕(如预期的那样)。 但是拉伸发生在视图空间的 Y 轴上(而不是模型)。

我知道,如果我沿 Z 轴设置比例,那么我会得到正确的结果。 但我的困惑是,我认为在 Y 轴上放大,然后旋转框,会给我正确的结果。

我错过了什么?

【问题讨论】:

标签: opengl matrix transformation


【解决方案1】:

OpenGL 在 column major order 中读取它的矩阵。结果是每个后续操作都是之前所有操作的预乘,而不是后乘。因此,每个对 OpenGL 操作的后续调用(glScale、glTranslate、glRotate)都是影响对象的第一个事物,它进入与你写它的顺序相反。

所以,你需要改变你的乘法顺序:

glRotatef(90, 0, 1, 0); // Notice how this is the first operation ...
// ... but will be applied after
glScalef(1, 10, 1); // This will be applied first, but is the last operation
// Zany, right?

说实话,当您编写程序并使用计算机必须以相反的顺序指定事物时,感觉不太直观。但是,被决定的图形之神就是他们希望 OpenGL 的矩阵堆栈的行为方式(以及 HLSL、GLSL 和其他系统:请参阅上面有关列优先排序的链接)。

【讨论】:

【解决方案2】:

如果您有一个表示 4x4 矩阵的数组,如下所示:

float mat[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };

然后将其加载到 OpenGL 矩阵中,OpenGL 会将前 4 个浮点数作为矩阵的第一列,第二个 4 个浮点数作为第二列,第三个 4 个浮点数作为矩阵的第 3 列,依此类推,等等

因此,每 4 个浮点数,OpenGL 就会将其视为另一列。这称为列主要顺序。 它将数据存储在列中。如果你必须转置一个列优先矩阵,它最终会变成一个行优先矩阵,反之亦然。

因为你有一个列主矩阵,你还需要使用列向量,这意味着你的乘法顺序是:M*v

为了证明这一点,请取一个简单的 2x2 矩阵和一个 2x1 列向量,乘以 M*v。设 K=transpose(M),r=行向量 (1x2)。

然后 M * v = r * K

归根结底,一旦你在代码中使用了列或行的主要符号,你就必须坚持下去。

【讨论】:

  • 内存中的存储顺序(行优先 vs. 列优先)与将向量相乘作为右侧列或左侧行的选择无关。例如,您可以在 GLSL 中从左侧乘以向量,即使矩阵以列优先顺序存储。
  • 是的,您可以在 GLSL 中从左侧乘以,但您必须记住转置矩阵。这就是为什么最好坚持一套方法——不那么混乱——只是回答 racarate 的问题。谢谢。
猜你喜欢
  • 2012-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多