C ++和OpenGLmatrix顺序之间的混淆(row-major vs column-major)

我对matrix定义感到困惑。 我有一个matrix类,基于以下观察结果,它包含一个我认为是行主要的float[16]

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

matrixAmatrixB在内存中具有相同的线性布局(即所有数字都是有序的)。 根据http://en.wikipedia.org/wiki/Row-major_order这表示行主布局。

 matrixA[0] == matrixB[0][0]; matrixA[3] == matrixB[0][3]; matrixA[4] == matrixB[1][0]; matrixA[7] == matrixB[1][3]; 

因此, matrixB[0] =行0, matrixB[1] =行1等。同样,这表示行主布局。

当我创build一个如下所示的转换matrix时,我的问题/困惑来了:

 1, 0, 0, transX 0, 1, 0, transY 0, 0, 1, transZ 0, 0, 0, 1 

其在内存中布置为{ 1, 0, 0, transX, 0, 1, 0, transY, 0, 0, 1, transZ, 0, 0, 0, 1 }

然后,当我调用glUniformMatrix4fv时 ,我需要设置转置标志为GL_FALSE,表明它是列专业,否则转换如翻译/规模等得不到正确应用:

如果转置是GL_FALSE,则假设每个matrix以列主要顺序提供。 如果转置是GL_TRUE,则假定每个matrix按行主要顺序提供。

为什么我的matrix,似乎是行大,需要作为列专业传递给OpenGL?

在opengl文档中使用的matrix符号不会描述OpenGLmatrix的内存中布局

如果认为放弃/忘记整个“行/列 – 专业”的事情会更容易。 这是因为除了行/列主要之外,程序员还可以决定如何在存储器中布置matrix(不pipe相邻元素是行还是列),除了表示之外,这增加了混淆。

OpenGLmatrix与directxmatrix具有相同的内存布局 。

 xx xy xz 0 yx yy yz 0 zx zy zz 0 px py pz 1 

要么

 { xx xy xz 0 yx yy yz 0 zx zy zz 0 px py pz 1 } 
  • x,y,z是描述matrix坐标系(相对于全局坐标系的局部坐标系)的3分量向量。

  • p是描述matrix坐标系原点的3分量vector。

这意味着翻译matrix应该像这样在内存中进行布局:

 { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, transX, transY, transZ, 1 }. 

把它留在那,其余的应该很容易。

—从旧的opengl引用faq–


9.005是OpenGLmatrix列主要还是行主要?

为了编程的目的,OpenGLmatrix是16值arrays,其基本向量在内存中连续布局。 平移组件占据了16元素matrix的第13,14,15个元素,其索引编号从1到16,如OpenGL 2.1规范的2.11.2节所述。

列专业和行专业纯粹是一个符号约定。 请注意,与列主matrix相乘后产生的结果与使用行主matrix的相乘结果相同。 OpenGL规范和OpenGL参考手册都使用列主要标志。 只要明确说明,您可以使用任何符号。

不幸的是,在规范和蓝皮书中使用列专业格式导致了OpenGL编程社区的无尽困惑。 专栏符号表明matrix并不像程序员期望的那样在内存中进行布局。


总结SigTerm和dsharlet的答案:在GLSL中变换vector的常用方法是用vector乘以变换matrix:

 mat4 T; vec4 v; vec4 v_transformed; v_transformed = T*v; 

为了达到这个目的,OpenGL希望T的内存布局如SigTerm所描述的那样,

 {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, transX, transY, transZ, 1 } 

也被称为“专栏”。 然而,在着色器代码中(如注释所示),您将vector与转换matrix右乘:

 v_transformed = v*T; 

这只有在T被转置时才会产生正确的结果,即具有布局

 { 1, 0, 0, transX, 0, 1, 0, transY, 0, 0, 1, transZ, 0, 0, 0, 1 } 

(即'行less校')。 既然你已经提供了正确的布局到你的着色器,即行专业,没有必要设置glUniform4vtranspose标志。

你正在处理两个不同的问题。

首先,你的例子正在处理内存布局。 你的[4] [4]数组是主要的行,因为你已经使用由Cmultidimensional arraybuild立的约定来匹配你的线性数组。

第二个问题是如何解释程序中的matrix的惯例。 glUniformMatrix4fv用于设置着色器参数。 无论您的变换是针对行vector还是列vector变换进行计算,都是您在着色器代码中如何使用matrix的问题。 因为你说你需要使用列向量,所以我假设你的着色器代码使用matrixA和列向量x来计算x' = A x

我会争辩说glUniformMatrix的文档是混淆的。 转置参数的描述是一个真正迂回的方式,只是说matrix转置或不转换。 OpenGL本身只是将数据传输到着色器,无论是否要转置它,都是您应该为您的程序build立的惯例。

这个链接有一些很好的进一步的讨论: http : //steve.hollasch.net/cgindex/math/matrix/column-vec.html