为什么要使用矩阵进行 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 功能强大且灵活,但如果说它们最擅长做一件事,那就是对向量进行一系列乘加运算(尽管较新的硬件在标量乘加运算上的效率与向量乘法运算一样高) - 添加)。矩阵向量乘法只是一系列向量乘加,更紧凑的结构可能效率较低。
也就是说,您的观点并非没有道理,我知道有一款成功的基于固定功能的游戏机,它的投影矩阵硬件寄存器有限,以利用您的确切观点,即投影矩阵通常未使用。
搜索投影矩阵的计算后(至少在 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 功能强大且灵活,但如果说它们最擅长做一件事,那就是对向量进行一系列乘加运算(尽管较新的硬件在标量乘加运算上的效率与向量乘法运算一样高) - 添加)。矩阵向量乘法只是一系列向量乘加,更紧凑的结构可能效率较低。
也就是说,您的观点并非没有道理,我知道有一款成功的基于固定功能的游戏机,它的投影矩阵硬件寄存器有限,以利用您的确切观点,即投影矩阵通常未使用。