这个话题已经讨论过很多次了。网上有很多关于OpenGL中矩阵内存布局的信息。可悲的是,不同的来源经常相互矛盾。
我的问题归结为:
当我有我的矩阵的三个基向量
bx,by和bz. 如果我想用它们制作一个矩阵以将它们插入着色器,它们在内存中的布局如何?
让我们澄清一下我所说的基向量是什么意思,因为我怀疑这也可能意味着不同的东西:
当我有一个 3D 模型时,它是 Z-up 并且我想将它沿 X 轴平放在我的世界空间中,然后bz是[1 0 0]. 即[0 0 2]模型空间中的顶点将被转换为[2 0 0]当该顶点乘以我的矩阵时,该矩阵bz作为 Z 轴的基向量。
来到 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]);
Run Code Online (Sandbox Code Playgroud)
因此,为了获得最佳性能,我应该在顶点着色器中预乘我的顶点(这样 GPU 可以使用点积等):
attribute vec4 vertex;
uniform mat4 mvp;
void main()
{
gl_Position = vertex * mvp;
}
Run Code Online (Sandbox Code Playgroud)
现在 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 ]
Run Code Online (Sandbox Code Playgroud)
或者:
[
0 4 8 12,
1 5 9 13,
2 6 10 14,
3 7 11 15,
]
Run Code Online (Sandbox Code Playgroud)
这意味着我必须将我的基本向量存储在这样的行中:
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
Run Code Online (Sandbox Code Playgroud)
因此,对于我想要平放的 3D 模型示例,它具有基本向量:
bx = [0 0 -1]
by = [0 1 0]
bz = [1 0 0]
Run Code Online (Sandbox Code Playgroud)
[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]
Run Code Online (Sandbox Code Playgroud)
正如预期的那样!
相反:
这个:正确的OpenGL矩阵格式? SO 问题,因此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
Run Code Online (Sandbox Code Playgroud)
对我来说,这两个都是 Khronos 官方文档的来源似乎相互矛盾。
有人可以向我解释一下吗?我做错了吗?真的有什么错误的信息吗?
FAQ是正确的,应该是:
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
Run Code Online (Sandbox Code Playgroud)
这是你的推理有缺陷。
假设您的基向量 bx, by, bz 是世界坐标中给出的模型基,那么从模型空间顶点 v 到世界空间顶点 Bv 的变换由基向量的线性组合给出:
B*v = bx*v.x + by*v.y + bz*v.z
Run Code Online (Sandbox Code Playgroud)
它不是 b 与 v 的点积。而是矩阵乘法,其中 B 具有上述形式。
取顶点 u 与 bx 的点积将回答相反的问题:给定一个世界空间 u,它在模型空间中沿轴 bx 的坐标是什么?因此,乘以转置矩阵transpose(B)将为您提供从世界空间到模型空间的转换。
| 归档时间: |
|
| 查看次数: |
242 次 |
| 最近记录: |