为什么要使用矩阵进行 3D 投影?

Why use a Matrix for 3D Projection?

搜索投影矩阵的计算后(至少在 OpenGL 中),

当我们有这么多空值时,为什么还要费心使用矩阵呢?我数了 9 个标记为 0 的条目,只有 7 个包含有用数据。为什么不使用类似的一维数组,将数据存储在类似列表的形状中呢?这不会节省内存和时间来创建可以操作矩阵的函数吗?我确信这整个论点也可以用于其他主题,这让我觉得,

在投影 3D 环境中使用矩阵的具体原因是什么?

这不仅与单个值有关,还与矩阵的数学属性有关。 零值与非零值一样重要! 值的布局本身就有意义!

特别是齐次变换矩阵(如 3D 投影矩阵)的前三列形成局部坐标 space 的基向量,第 4 列定义平移(在透视投影的情况下移动基点远离原点的奇异点)。

所以在 3D 中 space 每个位置有 3 个值:您必须将这三个值转换为屏幕上的 3 个值(第三个值转换为用于深度比较的值)和第四个(位置和目的地的)值用于透视变形。因此,对于原始位置的 4 个值中的每一个,您必须知道它对输出中的 4 个值中的每一个有多大贡献。如果它没有贡献(这同样重要),则为 0。因此您总共需要 4 · 4 = 16 个值。因此是一个 4×4 矩阵。

3D点(x,y,z)到2D图像坐标(X,Y)的投影可以计算为齐次坐标中的向量矩阵乘法:

[ a_00  a_01  a_02  a_03 ]   [ x ]    [ X W ]
[ a_10  a_11  a_12  a_13 ] * [ y ] =  [ Y W ]
[ a_20  a_21  a_22  a_23 ]   [ z ]    [ Z W ]
[ a_30  a_31  a_32  a_33 ]   [ 1 ]    [  W  ]

[ X W ]   [ x a_00 + y a_01 + z a_02 + a_03 ]
[ Y W ]   [ x a_10 + y a_11 + z a_12 + a_13 ]
[ Z W ] = [ x a_20 + y a_21 + z a_22 + a_23 ]
[  W  ]   [ x a_30 + y a_31 + z a_32 + a_33 ]

而像素坐标(X,Y)是由第一行和第二行除以第四行得到的。这一步就是齐次坐标到笛卡尔坐标的转换。

OpenGL 投影矩阵的第三行以 Z 成为投影深度的方式设置,即 z 值介于 n 和 [=18 之间=](近平面和远平面)映射到 -1...1。它用于深度 test/clipping。因为第四行是[0 0 -1 0],从齐次坐标到笛卡尔坐标的转换对应于除以-z,这导致透视变换(具有倒置深度)。

任何其他表达投影的方式都将涉及相同的步骤,即线性变换,然后除以 Z 以进行透视缩短。矩阵是线性代数中用于这些运算的常用表示法。

这并不特定于透视投影,但许多 3D 变换可以使用 4x4 矩阵表示,包括旋转、平移、缩放、剪切、反射、透视投影、正交投影等。

多个应该相继应用的变换也可以通过矩阵乘法组合成一个 4x4 矩阵。例如围绕 X、Y 和 Z 轴或 MVP 矩阵的旋转。这是模型-视图-投影矩阵,它将 3D 场景中一个对象的局部坐标系中的 3D 点转换为屏幕上的最终像素坐标。在这些组合矩阵上,所有分量都可以是非零的。

所以优点是一个单一的操作,向量矩阵乘法可用于所有这些情况,而不是几个不同的操作。它在 GPU 硬件上以高效的方式执行。

按原样使用投影矩阵可能非常罕见。通常,您更有可能将投影矩阵与世界和视图矩阵连接起来,然后一次性乘以世界视图投影矩阵。

此外,GPU 功能强大且灵活,但如果说它们最擅长做一件事,那就是对向量进行一系列乘加运算(尽管较新的硬件在标量乘加运算上的效率与向量乘法运算一样高) - 添加)。矩阵向量乘法只是一系列向量乘加,更紧凑的结构可能效率较低。

也就是说,您的观点并非没有道理,我知道有一款成功的基于固定功能的游戏机,它的投影矩阵硬件寄存器有限,以利用您的确切观点,即投影矩阵通常未使用。