【问题标题】:opengl matrix math multiplicationopengl矩阵数学乘法
【发布时间】:2015-07-31 08:28:19
【问题描述】:

我正在编写一个简单的 c 4x4 矩阵数学库并希望得到一些反馈,尤其是来自具有 opengl 经验的人。

通常有两种方法可以进行矩阵乘法。根据 wolfram alpha 的结果,我测试了这段代码,它可以工作,但我主要担心的是这个矩阵的顺序正确。

我的矩阵只是一个包含 16 个双精度数的数组。

做乘法的代码如下

out->m[0]  = ( a->m[0]  *  b->m[0]) + (a->m[1]  * b->m[4]) + (a->m[2]  *  b->m[8]) + (a->m[3]  * b->m[12] );
out->m[4]  = ( a->m[4]  *  b->m[0]) + (a->m[5]  * b->m[4]) + (a->m[6]  *  b->m[8]) + (a->m[7]  * b->m[12] );
out->m[8]  = ( a->m[8]  *  b->m[0]) + (a->m[9]  * b->m[4]) + (a->m[10] *  b->m[8]) + (a->m[11] * b->m[12] );
out->m[12] = ( a->m[12] *  b->m[0]) + (a->m[13] * b->m[4]) + (a->m[14] *  b->m[8]) + (a->m[15] * b->m[12] );

out->m[1]  = ( a->m[0]  *  b->m[1]) + (a->m[1]  * b->m[5]) + (a->m[2]  * b->m[9])  + (a->m[3]  * b->m[13] );
out->m[5]  = ( a->m[4]  *  b->m[1]) + (a->m[5]  * b->m[5]) + (a->m[6]  * b->m[9])  + (a->m[7]  * b->m[13] );
out->m[9]  = ( a->m[8]  *  b->m[1]) + (a->m[9]  * b->m[5]) + (a->m[10] * b->m[9])  + (a->m[11] * b->m[13] );
out->m[13] = ( a->m[12] *  b->m[1]) + (a->m[13] * b->m[5]) + (a->m[14] * b->m[9])  + (a->m[15] * b->m[13] );

out->m[2]  = ( a->m[0]  *  b->m[2]) + (a->m[1]  * b->m[6]) + (a->m[2]  * b->m[10]) + (a->m[3]  * b->m[14] );
out->m[6]  = ( a->m[4]  *  b->m[2]) + (a->m[5]  * b->m[6]) + (a->m[6]  * b->m[10]) + (a->m[7]  * b->m[14] );
out->m[10] = ( a->m[8]  *  b->m[2]) + (a->m[9]  * b->m[6]) + (a->m[10] * b->m[10]) + (a->m[11] * b->m[14] );
out->m[14] = ( a->m[12] *  b->m[2]) + (a->m[13] * b->m[6]) + (a->m[14] * b->m[10]) + (a->m[15] * b->m[14] );

out->m[3]  = ( a->m[0]  *  b->m[3]) + (a->m[1]  * b->m[7]) + (a->m[2]  * b->m[11]) + (a->m[3]  * b->m[15] );
out->m[7]  = ( a->m[4]  *  b->m[3]) + (a->m[5]  * b->m[7]) + (a->m[6]  * b->m[11]) + (a->m[7]  * b->m[15] );
out->m[11] = ( a->m[8]  *  b->m[3]) + (a->m[9]  * b->m[7]) + (a->m[10] * b->m[11]) + (a->m[11] * b->m[15] );
out->m[15] = ( a->m[12] *  b->m[3]) + (a->m[13] * b->m[7]) + (a->m[14] * b->m[11]) + (a->m[15] * b->m[15] );

我想确保这会给我正确的结果来设置我的转换矩阵。

矩阵 m = 1,3,4,-1,5,6,7,-1,8,8,8,-1,0,0,0,1 它在内存中的排列方式如下:

1,3,4,-1
5,6,7,-1
8,8,8,-1
0,0,0,1

我认为这是 opengl 将其矩阵布置为 16 个数字的方式。

使用我的代码我的答案是

[   48.000000   53.000000   57.000000   -9.000000   ]
[   91.000000   107.000000  118.000000  -19.000000  ]
[   112.000000  136.000000  152.000000  -25.000000  ]
[   0.000000    0.000000    0.000000    1.000000    ]

这是 wolfram alpha 答案的转置。

(48 | 91  | 112 | 0
 53 | 107 | 136 | 0
 57 | 118 | 152 | 0
 -9 | -19 | -25 | 1)

通常看起来像这样,顶点v模型、视图、投影矩阵

position = projection * view * model * v

【问题讨论】:

  • 你知道,循环是一回事,任何现代的、体面的编译器实际上都能够展开它,并且通常还检测到它是可向量化的。即使编译器没有捕捉到它,现代 CPU 在内部向量化该代码时已经变得非常高效。
  • @datenwolf 如果编译器没有为代码生成指令,CPU 如何对代码进行矢量化处理?
  • 我希望本文继续关注这个人,请继续围绕该主题进行讨论。我想避免它成为关于 CPU 或编译器能为您做什么或不能做什么的讨论。
  • 请说明您的布局。内存是一维的,所以你不能有一个二维的内存布局。另一方面,矩阵是二维的,因此您的矩阵表示 (m = 1, 3, 4 ...) 没有意义。还有如何解释这些结果?
  • 我猜,您可能误解了 Wolfram Alpha 的输出。如果你计算了上面矩阵的平方,这就是转置的结果(正确的结果第一行第二列有53)。

标签: c opengl matrix 3d


【解决方案1】:

我不能告诉你为什么你的结果不同,但一个帮助是,如果你将矩阵发送到一个 GLSL 统一的 dMat4,你可以使用 OpenGL 的内置转置功能来获得正确的矩阵对齐:

glUniformMatrix4fv( Uniform_Location, 1, GL_TRUE, MatrixPointer );

第三个参数表示,OpenGL是否应该在设置uniform之前转置矩阵。

【讨论】:

  • 这可能是最好的评论,如果没有人有更好的解决方案,这可能是答案。结果不同的一个原因通常是矩阵乘法是编程中的行专业,但opengl需要列专业。这是我第一次写这样的库,所以有很多地方可以做的。至少有了这个选项,我知道至少在调试时有一种方法可以快速转置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-05
  • 1970-01-01
  • 2011-10-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多