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 } };
matrixA
和matrixB
在内存中具有相同的线性布局(即所有数字都是有序的)。 根据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校')。 既然你已经提供了正确的布局到你的着色器,即行专业,没有必要设置glUniform4v
的transpose
标志。
你正在处理两个不同的问题。
首先,你的例子正在处理内存布局。 你的[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