openGL变换矩阵在Shader中实际情况

    一直以来关于各种论坛、MDSN、khronos、gl spec等等都将openGL的变换矩阵看成是用column-major order来排列元素的,并且用 glMat * colVector来实现空间变换。与之相对的,是用rowVector * row-major order type mat。 这两种变换方式用线代的观点很好理解,并且互为转置。但是,实际情况即在shader中,openGL 真的是这样的吗?

    glLoadMatrix(*ptr)和glUniformMatrix(location, count, transpose = false, *ptr)是gl中两种默认的加载变换矩阵的API,分别用于默认渲染管道和含有shader的渲染管道。在顶点着色器中这二者的执行都是gl_pos = proj*modelView*vert

使用两种方法渲染同一场景:

1.glLoadMatrix(ptr),这里ptr传入的是 C type的按照行排列的double[16]

2.glUniformMatrix(location, count, false , ptr)这里ptr 的排列同上。

两种方法渲染场景的初始姿态是完全一致的:

1.

openGL变换矩阵在Shader中实际情况

2.

openGL变换矩阵在Shader中实际情况

    在利用方法2渲染的时候,需要访问当前的视点位置即modelView变换中平移量的相反量,如果gl中的变换矩阵是column-major order排列的,那么平移量应该位于modeView[0][3]->modelView[2][3],但是按照这样的方式计算光照时得到的场景是一片漆黑,将平移量改为modelView[3][0]->modelView[3][2]后预期场景生成了。在利用方法2时,我们并没有对加载的变换矩阵进行转置,变换矩阵的平移量在shader中应该位于第三行(从0行起算)。那么为何使用方法1得到的结果和方法2一致(仅仅指姿态一致),MSDN、khronos不是说利用glLoadMatrix加载变换矩阵后,矩阵在gl中实际表现为原始的转置,即平移量表现在第三列。为了验证这个疑问,使用glGetDoublev得到当前的变换矩阵,发现矩阵元素实际还是按行排列的。

    所以,可知行序排列的变换矩阵被加载到渲染管道时并没有发生所谓的转置,正如设计opengl中column-major order的作者所说的那样----“The data elements 0 through 15 are in the same order for a "row major" matrix as for a "column major" matrix. To beat it to death: the OpenGL matrix stores translation values in elements 12,13,14, which is exactly where they are stored in IRIS GL”(http://steve.hollasch.net/cgindex/math/matrix/column-vec.html).该作者又说

Recent mathematical treatments of linear algebra and related fields invariably treat vectors as columns (there are some technical reasons for this). For some reason, this has not been the case in computer graphics, where vectors were written as rows, thus transposing everything from standard mathematical usage. When I wrote the OpenGL spec, I decided to do my part to right this heinous inconsistency. Thus the spec is written with vectors treated as columns, with a matrix correspondingly applied on the left of a column.

The one difficulty was compatibility with the current GL, where vectors had been written as rows. So I come up with this subterfuge: say that matrices in OpenGL are stored in column major order. The point is that you could rewrite the spec with everything transposed (with vectors written as rows), and everything would be exactly the same as it was, including the row major ordering of matrices. 大意是:在线代里面是 行主序变换矩阵 * 列向量,但是在CG里面向量又被表现为行,因此与线代里面相差一个转置。当在写

OpenGL spec时这家伙为了一致性,又改口为gl里面的实现和线代是相同的。但是这又与当时的gl的实现不怎么兼容,在gl中向量表现为行(变换矩阵*行向量,用线代的思想考虑行不通或者说计算的结果不正确)。因此这家伙又换了个借口,说gl中的变换矩阵是按照

column major order存储的即其想表达的意思是“

变换矩阵的每一列依次与行向量进行计算,得到一个分:Mat[][i] * rowVector”.

       根据以上分析,gl所谓的变换矩阵是按

column major order排列这一说法完全是为了兼容opengl内部的矩阵变换的实现(opengl内部维护的矩阵变换可能并没有像线代中定义的“矩阵的一行*列向量”)----矩阵的一列* 行,本质上在没有人为地调用glloadtransposematrix时,矩阵元素的排列在gl内部是没有发生变换的。