OpenGL:如何在内存

时间:2017-07-04 13:27:40

标签: opengl matrix

这个话题已经讨论过很多次了。关于互联网上OpenGL中矩阵的内存布局有很多信息。可悲的是,不同的来源经常相互矛盾。

我的问题归结为:

  

当我的矩阵bxbybz有三个基矢量时。如果我想用它们制作矩阵将它们插入到着色器中,它们如何在内存中布局?

让我们澄清基本向量的含义,因为我怀疑这也意味着不同的东西:

如果我有一个3D模型,那就是Z-up,我想沿着X轴将它平放在我的世界空间中,那么bz就是[1 0 0]。即当该顶点乘以具有[0 0 2]作为Z轴基本向量的矩阵时,模型空间中的顶点[2 0 0]将转换为bz

来到OpenGL矩阵内存布局:

根据GLSL规范(GLSL Spec p.110),它说:

vec3 v, u;
mat3 m;
u = v * m;

is equivalent to

u.x = dot(v, m[0]); // m[0] is the left column of m
u.y = dot(v, m[1]); // dot(a,b) is the inner (dot) product of a and b
u.z = dot(v, m[2]);

所以,为了获得最佳性能,我应该在顶点着色器中预先设置我的顶点(这样GPU可以使用点积等等):

attribute vec4 vertex;
uniform mat4 mvp;
void main()
{
    gl_Position = vertex * mvp;
}

现在OpenGL被称为列专业(GLSL Spec p 101)。即列在内存中连续布局:

[ column 0 | column 1 | column 2  | column 3    ]
[ 0 1 2 3  | 4 5 6 7  | 8 9 10 11 | 12 13 14 15 ]

或:

[
    0  4  8 12,
    1  5  9 13,
    2  6 10 14,
    3  7 11 15,
]

这意味着我必须将我的基本向量存储在这样的行中:

bx.x bx.y bx.z 0
by.x by.y by.z 0
bz.x bz.y bz.z 0
0    0    0    1

因此,对于我想要平放的3D模型的示例,它具有基本向量:

bx = [0 0 -1]
by = [0 1  0]
bz = [1 0  0]

上面的模型顶点[0 0 2]将在顶点着色器中像dis一样进行变换:

// m[0] is [ 0 0 1 0]
// m[1] is [ 0 1 0 0]
// m[2] is [-1 0 0 0]
// v    is [ 0 0 2 1]
u.x = dot([ 0 0 2 1], [ 0 0 1 0]);
u.y = dot([ 0 0 2 1], [ 0 1 0 0]);
u.z = dot([ 0 0 2 1], [-1 0 0 0]);
// u    is [ 2 0 0]

正如所料!

恰恰相反:

这:Correct OpenGL matrix format? 因此问题以及OpenGL Faq状态:

  

出于编程目的,OpenGL矩阵是16值数组,其基本向量在内存中连续排列。转换组件占据16元素矩阵的第13,14和15个元素,其中索引的编号从1到16,如OpenGL 2.1规范的2.11.2节所述。

这表示我的基本向量应该按照以下列列出:

bx.x by.x bz.x 0
bx.y by.y bz.y 0
bx.z by.z bz.z 0
0    0    0    1

对我来说,这两个来自Khronos的官方文件似乎互相矛盾。

有人可以向我解释一下吗?我弄错了吗?确实有一些错误的信息吗?

1 个答案:

答案 0 :(得分:4)

常见问题解答是正确的,应该是:

<?xml version="1.0" encoding="utf-16"?>
<Root>
    <NameOfMyRoot xmlns:ns="myNamespace">
        <ns:SomeString></ns:SomeString>
    </NameOfMyRoot>
</Root>

这是你的理由存在缺陷。

假设您的基矢量bx,by,bz是世界坐标中给出的模型基础,那么从模型空间顶点v到世界空间顶点Bv的变换由基矢量的线性组合给出:

bx.x by.x bz.x 0
bx.y by.y bz.y 0
bx.z by.z bz.z 0
0    0    0    1

它不是b与v的点积。而是它的矩阵乘法,其中B是上述形式。

采用顶点u和bx的点积将回答相反的问题:给定一个世界空间你沿着轴bx在模型空间中的坐标是什么?因此,乘以转置矩阵B*v = bx*v.x + by*v.y + bz*v.z 将为您提供从世界空间到模型空间的转换。