C++ 和 OpenGL 矩阵顺序之间的混淆(行优先 vs 列优先)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17717600/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Confusion between C++ and OpenGL matrix order (row-major vs column-major)
提问by Mark Ingram
I'm getting thoroughly confused over matrix definitions. I have a matrix class, which holds a float[16]
which I assumed is row-major, based on the following observations:
我对矩阵定义感到非常困惑。我有一个矩阵类,它包含一个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
and matrixB
both have the same linear layout in memory (i.e. all numbers are in order). According to http://en.wikipedia.org/wiki/Row-major_orderthis indicates a row-major layout.
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];
Therefore, matrixB[0]
= row 0, matrixB[1]
= row 1, etc. Again, this indicates row-major layout.
因此,matrixB[0]
= 第 0 行,matrixB[1]
= 第 1 行,等等。同样,这表示行优先布局。
My problem / confusion comes when I create a translation matrix which looks like:
当我创建一个如下所示的翻译矩阵时,我的问题/困惑就出现了:
1, 0, 0, transX
0, 1, 0, transY
0, 0, 1, transZ
0, 0, 0, 1
Which is laid out in memory as, { 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 }
。
Then when I call glUniformMatrix4fv, I need to set the transpose flag to GL_FALSE, indicating that it's column-major, else transforms such as translate / scale etc don't get applied correctly:
然后,当我调用glUniformMatrix4fv 时,我需要将转置标志设置为 GL_FALSE,表明它是列优先的,否则转换/缩放等转换无法正确应用:
If transpose is GL_FALSE, each matrix is assumed to be supplied in column major order. If transpose is GL_TRUE, each matrix is assumed to be supplied in row major order.
如果 transpose 是 GL_FALSE,则假定每个矩阵按列主要顺序提供。如果 transpose 为 GL_TRUE,则假定每个矩阵按行主顺序提供。
Why does my matrix, which appears to be row-major, need to be passed to OpenGL as column-major?
为什么我的矩阵看起来是行优先的,需要作为列优先传递给 OpenGL?
采纳答案by SigTerm
matrix notation used in opengl documentation does not describe in-memory layout for OpenGL matrices
opengl 文档中使用的矩阵表示法没有描述 OpenGL 矩阵的内存布局
If think it'll be easier if you drop/forget about the entire "row/column-major" thing. That's because in addition to row/column major, the programmer can also decide how he would want to lay out the matrix in the memory (whether adjacent elements form rows or columns), in addition to the notation, which adds to confusion.
如果您认为放弃/忘记整个“行/列主要”的事情会更容易。那是因为除了行/列专业之外,程序员还可以决定他希望如何在内存中布置矩阵(相邻元素形成行还是列),以及表示法,这会增加混淆。
OpenGL matrices have same memory layout as directx matrices.
OpenGL 矩阵与 directx 矩阵具有相同的内存布局。
x.x x.y x.z 0
y.x y.y y.z 0
z.x z.y z.z 0
p.x p.y p.z 1
or
或者
{ x.x x.y x.z 0 y.x y.y y.z 0 z.x z.y z.z 0 p.x p.y p.z 1 }
x, y, z are 3-component vectors describing the matrix coordinate system (local coordinate system within relative to the global coordinate system).
p is a 3-component vector describing the origin of matrix coordinate system.
x、y、z 是描述矩阵坐标系(相对于全局坐标系内的局部坐标系)的 3 分量向量。
p 是描述矩阵坐标系原点的 3 分量向量。
Which means that the translation matrix should be laid out in memory like this:
这意味着翻译矩阵应该像这样在内存中布置:
{ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, transX, transY, transZ, 1 }.
Leave it at that, and the rest should be easy.
就这样吧,剩下的应该很容易了。
---citation from old opengl faq--
---引自旧的opengl faq--
9.005 Are OpenGL matrices column-major or row-major?
For programming purposes, OpenGL matrices are 16-value arrays with base vectors laid out contiguously in memory. The translation components occupy the 13th, 14th, and 15th elements of the 16-element matrix, where indices are numbered from 1 to 16 as described in section 2.11.2 of the OpenGL 2.1 Specification.
Column-major versus row-major is purely a notational convention. Note that post-multiplying with column-major matrices produces the same result as pre-multiplying with row-major matrices. The OpenGL Specification and the OpenGL Reference Manual both use column-major notation. You can use any notation, as long as it's clearly stated.
Sadly, the use of column-major format in the spec and blue book has resulted in endless confusion in the OpenGL programming community. Column-major notation suggests that matrices are not laid out in memory as a programmer would expect.
9.005 OpenGL 矩阵是列优先还是行优先?
出于编程目的,OpenGL 矩阵是 16 值数组,其中基向量在内存中连续排列。转换组件占据 16 元素矩阵的第 13、14 和 15 个元素,其中索引从 1 到 16 编号,如 OpenGL 2.1 规范的第 2.11.2 节所述。
列优先与行优先纯粹是一种符号约定。请注意,使用列主矩阵进行后乘会产生与使用行主矩阵进行预乘相同的结果。OpenGL 规范和 OpenGL 参考手册都使用列优先表示法。您可以使用任何表示法,只要明确说明即可。
遗憾的是,在规范和蓝皮书中使用列主要格式导致 OpenGL 编程社区无休止的混乱。列优先表示法表明矩阵并不像程序员所期望的那样在内存中布置。
回答by Roberto
To summarize the answers by SigTerm and dsharlet: The usual way to transform a vector in GLSL is to left-multiply the vector by the transformation matrix:
总结 SigTerm 和 dsharlet 的答案:在 GLSL 中变换向量的常用方法是将向量左乘以变换矩阵:
mat4 T; vec4 v; vec4 v_transformed;
v_transformed = T*v;
In order for that to work, OpenGL expects the memory layout of T
to be, as described by SigTerm,
为了使其工作,OpenGL 期望内存布局为T
,如 SigTerm 所述,
{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, transX, transY, transZ, 1 }
which is also called 'column major'. In your shader code (as indicated by your comments), however, you right-multiplied the vector by the transformation matrix:
这也被称为“专栏专业”。但是,在您的着色器代码中(如您的注释所示),您将向量乘以变换矩阵:
v_transformed = v*T;
which only yields the correct result if T
is transposed, i.e. has the layout
只有在T
转置时才会产生正确的结果,即具有布局
{ 1, 0, 0, transX, 0, 1, 0, transY, 0, 0, 1, transZ, 0, 0, 0, 1 }
(i.e. 'row major'). Since you already provided the correct layout to your shader, namely row major, it was not necessary to set the transpose
flag of glUniform4v
.
(即'行专业')。既然你已经提供了正确的布局着色器,即行重大,这是没有必要设置transpose
的标志glUniform4v
。
回答by dsharlet
You are dealing with two separate issues.
您正在处理两个不同的问题。
First, your examples are dealing with the memory layout. Your [4][4] array is row major because you've used the convention established by C multi-dimensional arrays to match your linear array.
首先,您的示例正在处理内存布局。您的 [4][4] 数组是行主要的,因为您使用了 C 多维数组建立的约定来匹配您的线性数组。
The second issue is a matter of convention for how you interpret matrices in your program. glUniformMatrix4fvis used to set a shader parameter. Whether your transform is computed for a row vectoror column vectortransform is a matter of how you use the matrix in your shader code. Because you say you need to use column vectors, I assume your shader code is using the matrix Aand a column vector xto compute x'= A x.
第二个问题是关于如何解释程序中矩阵的约定问题。glUniformMatrix4fv用于设置着色器参数。您的变换是针对行向量还是列向量进行计算,这取决于您如何在着色器代码中使用矩阵。因为您说您需要使用列向量,所以我假设您的着色器代码使用矩阵A和列向量x来计算x'= A x。
I would argue that the documentation of glUniformMatrixis confusing. The description of the transpose parameter is a really roundabout way of just saying that the matrix is transposed or it isn't. OpenGL itself is just transporting that data to your shader, whether you want to transpose it or not is a matter of convention you should establish for your program.
我认为glUniformMatrix的文档令人困惑。转置参数的描述是一种非常迂回的方式,只是说矩阵已转置或不是。OpenGL 本身只是将这些数据传输到您的着色器,无论您是否要转置它都是您应该为程序建立的约定问题。
This link has some good further discussion: http://steve.hollasch.net/cgindex/math/matrix/column-vec.html
这个链接有一些很好的进一步讨论:http: //steve.hollasch.net/cgindex/math/matrix/column-vec.html