变换 (Transform)

变换是计算机图形学的基石,它让我们可以移动、旋转、缩放、变形场景中的一切。熟练掌握变换不仅是面试的要求,更是写出高效、正确渲染代码的关键。本章的笔记将围绕“是什么”、“为什么”以及“怎么用”来展开。


基本变换

一、 变换的基础概念 (Core Concepts)

在深入了解具体的变换矩阵之前,我们需要先建立几个核心认知。

  • 核心观点: 图形学中的大部分操作,都是通过将点或向量与一个矩阵相乘来实现的。为了统一处理平移、旋转、缩放等操作,我们引入了仿射变换和齐次坐标。

  • 关键术语:

    • 线性变换 (Linear Transform): 只保留向量加法和标量乘法的变换,例如旋转缩放。可以用一个 矩阵表示。它无法表达平移
    • 仿射变换 (Affine Transform): 一个线性变换 + 一次平移。这是我们在实时渲染中最常用的变换类型。它保持直线的“直”和平行线的“平行”。几乎所有基础变换(平移、旋转、缩放、剪切)都是仿射变换。
    • 齐次坐标 (Homogeneous Notation): 为了将仿射变换统一成单一的矩阵乘法,我们将三维坐标扩展到四维。这是图形学中最优雅的数学技巧之一。
      • 点 (Point): 表示为 分量为1,意味着它可以被平移。
      • 方向/向量 (Vector): 表示为 分量为0,意味着它不会受到平移变换的影响,这完全符合物理直觉(一个方向无论在哪里,都是同一个方向)。

二、 基础仿射变换 (Basic Affine Transforms)

这部分是基础工具箱,你需要对每个变换的矩阵形式和特性了然于胸。

4.1.1 平移 (Translation)

  • 核心观点: 将物体从一个位置移动到另一个位置。
  • 矩阵表示:
  • 关键特性:
    • 只改变点的位置,不影响方向向量。
    • 逆变换: 向相反方向平移相同距离,即

4.1.2 旋转 (Rotation)

  • 核心观点: 围绕一个通过原点的轴线旋转物体。
  • 矩阵表示: 绕三大主轴旋转的矩阵
  • 关键特性:
    • 正交矩阵 (Orthogonal Matrix): 这是旋转矩阵最重要的属性。它意味着矩阵的逆矩阵等于其转置矩阵 ()。计算转置远比计算通用逆矩阵快得多,这是一个重要的性能优化点。
    • 刚体变换 (Rigid-Body Transform): 旋转保持物体的形状、尺寸、角度和距离不变。
    • 示例:绕任意点 旋转: 这是一个经典的复合变换思路,可以概括为“三明治”法则:
      1. 移回原点: 将物体平移,使点 与坐标原点重合 ()。
      2. 执行旋转: 绕原点进行旋转 ()。
      3. 移回原位: 进行反向平移,将物体移回 ()。
      • 组合矩阵: (注意:最先应用的变换在最右边)。

4.1.3 缩放 (Scaling)

  • 核心观点: 放大或缩小物体。
  • 矩阵表示:
  • 关键特性:
    • 均匀缩放 (Uniform Scaling): 时。
    • 非均匀缩放 (Non-uniform Scaling): 不相等时。这是导致法线变换问题的罪魁祸首。
    • 反射/镜像 (Reflection/Mirror): 当有奇数个(1或3个)缩放因子为负数时。这会改变物体的手性 (Handedness),例如,使逆时针的三角形顶点顺序变为顺时针,可能导致背面剔除和光照计算错误。
    • 检测反射: 计算左上角 子矩阵的行列式,如果为负,则为反射变换。
    • 逆变换: 使用缩放因子的倒数进行缩放,即

4.1.4 剪切 (Shearing)

  • 核心观点: 扭曲、倾斜物体,就像推倒一叠书。
  • 矩阵表示: ,表示用 坐标去影响 坐标。例如, 表示用 坐标的值去改变 坐标。
  • 关键特性:
    • 保体变换 (Volume-Preserving): 剪切变换的行列式为1,不会改变物体的体积(或二维下的面积)。
    • 逆变换: 向相反方向剪切,即

三、 组合与运用 (Composition and Application)

4.1.5 变换的连接 (Concatenation)

  • 核心观点: 将多个变换矩阵预先乘起来,形成一个单一的复合矩阵,可以极大地提升性能。
  • 关键特性:
    • 顺序至关重要: 矩阵乘法不满足交换律 ()。先旋转再缩放,和先缩放再旋转,结果完全不同。
    • 应用顺序: 在列主序数学约定下(本书采用),矩阵从右向左依次作用于顶点。例如,组合矩阵 应用于顶点 时,写作 ,实际计算顺序是 ,即先缩放,再旋转,最后平移。这是最常见的物体变换顺序。
    • 满足结合律: 。这意味着我们可以任意地对矩阵进行分组预乘,这在场景图等层级结构中非常有用。

4.1.6 刚体变换 (Rigid-Body Transform)

  • 核心观点: 仅由平移旋转构成的变换。它能改变物体的位置和朝向,但绝不改变其形状或大小。
  • 矩阵形式: 左上角是 的旋转矩阵,最后一列是平移向量。
  • 快速求逆: 无需使用通用的慢速求逆算法。其逆变换为先反向旋转,再反向平移

4.1.7 法线变换 (Normal Transform) - [面试高频考点]

  • 核心问题: 当模型经过非均匀缩放剪切时,如果用同一个变换矩阵去变换法线,变换后的法线将不再垂直于变换后的表面。
  • 正确方法: 变换法线需要使用原始模型变换矩阵 逆转置矩阵 (Inverse Transpose),即
  • 实践中的优化与判断:
    1. 如果变换是刚体变换(只有旋转和平移): 此时 的左上角 部分是正交矩阵 。因此,可以直接使用原矩阵 的左上角 部分来变换法线,且无需重新归一化。
    2. 如果变换包含均匀缩放: 仍然可以直接用 部分,但变换后的法线需要重新归一化
    3. 只有当变换包含非均匀缩放或剪切时: 才必须计算逆转置矩阵。

4.1.8 计算逆矩阵 (Calculating Inverses)

  • 核心观点: 根据矩阵的类型,选择最高效的求逆方法。
  • 求逆策略(由快到慢):
    1. 构造法: 如果你知道变换是由一系列简单变换构成的(如 ),则其逆矩阵就是反向变换的逆序组合)。这是最快且最精确的方法。
    2. 利用正交性: 如果矩阵是正交的(如纯旋转矩阵),其逆矩阵就是其转置 ()。
    3. 通用算法: 当以上条件都不满足时,才使用伴随矩阵法、高斯消元等通用方法。这些方法计算量大,应尽量避免。

我们学习了图形学变换的“字母表”——平移、旋转、缩放等基础变换。更重要的是,我们理解了如何使用齐次坐标将它们组合成强大的工具,并掌握了刚体变换、法线变换这些在实际开发中至关重要的概念。

接下来的内容,如欧拉角、四元数,将为我们提供更灵活、更稳定的方式来处理旋转。顶点混合与变形则是角色动画的基础。投影变换则是将三维世界最终展现在二维屏幕上的最后一步。牢固掌握本章内容,将为后续的学习打下坚实的基础。


特殊矩阵变换

这一部分将聚焦于一些更具体、更特殊的矩阵操作,它们在日常的引擎开发中非常实用。 在掌握了基础变换之后,我们需要学习一些更高级的技巧来应对复杂的旋转需求。本节将介绍欧拉变换、矩阵分解以及绕任意轴旋转等在实际开发中频繁使用的操作。

4.2.1 欧拉变换 (Euler Transform)

  • 核心观点: 欧拉变换提供了一种非常直观的方式来描述和构建旋转,它将复杂的空间旋转分解为三次绕主轴的连续旋转。这非常符合人类的思维习惯。

  • 关键术语:

    • 欧拉角 (Euler Angles): 三个角度值,通常定义为 航向角 (Head/Yaw)俯仰角 (Pitch)滚转角 (Roll)
      • Head/Yaw (偏航):y 轴旋转,如同“摇头”。
      • Pitch (俯仰):x 轴旋转,如同“点头”。
      • Roll (滚转):z 轴旋转,如同“歪头”。
  • 工作原理:

    • 欧拉变换矩阵 是三个独立旋转矩阵的乘积。旋转顺序至关重要,不同的顺序会产生完全不同的结果。本书及常用图形学约定采用的顺序是:先绕Y轴(Head),再绕X轴(Pitch),最后绕Z轴(Roll)
    • 公式表示: 注意:最先应用的变换(绕Y轴)在公式的最右侧。
  • 关键特性与注意事项:

    • 正交性: 由于是三个旋转矩阵的组合,欧拉变换矩阵本身也是正交矩阵,其逆等于其转置 ()。
    • 坐标系约定 (y-up vs. z-up): 这是一个在不同软件和引擎中常见的“坑”。游戏和影视行业通常采用 y-up (Y轴朝上),而建筑和工业设计领域常用 z-up (Z轴朝上)。理解你当前工作的环境使用的是哪种约定至关重要。
    • 核心缺陷:
      1. 插值困难: 不能简单地对两组欧拉角进行线性插值来获得平滑的旋转动画,因为可能存在多组欧拉角描述同一个方向。
      2. 万向节死锁 (Gimbal Lock): 这是欧拉变换最著名、最致命的缺陷。

4.2.2 从矩阵中提取欧拉角 & 万向节死锁 (Gimbal Lock)

  • 核心观点: 我们可以从一个已知的纯旋转矩阵中,反向推算出生成它的欧拉角参数。这个过程能帮助我们深入理解“万向节死锁”的本质。

  • 参数提取 (通用情况):

    • 通过将欧拉变换的展开矩阵(公式4.23)与给定的旋转矩阵 的元素 一一对应,可以解出 h, p, r
    • 求解公式: atan2(y, x) 是一个双参数的反正切函数,比 atan(y/x) 更健壮,能处理所有象限。
  • 万向节死锁 (Gimbal Lock) 详解:

    • 现象:俯仰角 (Pitch) 为 时,第一次旋转(绕Y轴)和第三次旋转(绕Z轴)的旋转轴会重合到同一条世界空间轴线上。这导致系统丢失了一个旋转自由度,无论怎么调整 Head 和 Roll,都只能在同一个平面上旋转,无法实现某些方向的旋转。
    • 数学原因: 时, 。此时,上述提取公式中的 atan2 函数的两个参数都会变为0,导致无法求解。矩阵本身的形式也发生了退化,hr 的影响被合并为 r+hr-h,失去了独立性。
    • 解决方法: 当检测到 (即 ) 时,我们就知道发生了死锁。此时,可以约定一个角度为0(例如 h = 0),然后解出另一个角度的值,如
  • 应用实例 (约束变换):

    • 这是一个非常实用的技巧。比如,要模拟一个只能绕自身x轴旋转的扳手。当输入设备提供一个任意旋转 时,我们可以:
      1. 提取出欧拉角 (h, p, r)
      2. 抛弃不想要的旋转,只保留我们需要的 p (绕x轴的俯仰角)。
      3. 重新构建一个新的、纯净的旋转矩阵 ,并应用到扳手上。

4.2.3 矩阵分解 (Matrix Decomposition)

  • 核心观点: 将一个复杂的、未知的 仿射变换矩阵,拆解回其基本组成部分:平移(T)、旋转(R)、缩放(S)和剪切(K)
  • 为何重要 (应用场景):
    • 从层级变换后的最终矩阵中提取某个对象的真实缩放比例
    • 当动画系统只支持分别设置TRS时,需要分解矩阵来驱动。
    • 判断一个物体是否只经历了刚体变换(即没有缩放和剪切)。
    • 移除不想要的变换,比如从一个扫描或建模工具导出的模型矩阵中消除剪切
  • 实现思路:
    • 平移最容易提取,它就是 矩阵的最后一列
    • 分离旋转、缩放、剪切则复杂得多,需要专门的算法(如QR分解或极分解)。幸运的是,有成熟的开源代码和论文可以参考。

4.2.4 绕任意轴旋转 (Rotation Around an Arbitrary Axis)

  • 核心观点: 构建一个矩阵,使其能够围绕空间中的任意单位向量轴 旋转 度。

  • 方法一:基变换法 ("三明治"思路)

    • 这是最直观的构建方法,分三步走:
      1. 对齐: 构建一个旋转矩阵 ,将任意轴 旋转至与世界坐标系的某个主轴(如X轴)重合。这一步的关键是基于 构建一个完整的标准正交基
      2. 旋转: 现在问题简化为绕X轴旋转 度,即应用
      3. 复原: 将坐标系旋转回去,即应用 的逆矩阵 (也就是 )。
    • 最终矩阵:
  • 方法二:直接公式法 (Rodrigues' Rotation Formula)

    • 存在一个直接从轴 和角度 计算出旋转矩阵的数学公式,无需进行多次矩阵乘法。这个公式在性能要求高的场景下非常有用。
    • 公式表示: 其中

总结

欧拉角因其直观性而被广泛使用,但必须警惕万向节死锁。四元数(将在下一节讨论)是解决此问题的更优方案。矩阵分解和绕任意轴旋转是解决实际渲染和工具开发问题的强大武器。理解这些特殊操作的原理和适用场景,将使你在处理复杂的3D变换时更加得心应手。


四元数是现代3D引擎中处理旋转的基石。

**四元数 (Quaternions) **

欢迎来到本章最核心、也是最具挑战性的部分——四元数。如果你之前对欧拉角的“万向节死锁”感到困惑,那么四元数就是你一直在寻找的优雅解药。它最初可能看起来有些抽象,但一旦你掌握了它的几何意义,它就会成为你工具箱里最强大的武器之一。


一、 为什么需要四元数?(The "Why")

  • 核心观点: 四元数是目前表示3D旋转和方向的最佳方式。它解决了欧拉角和矩阵表示法的诸多痛点,特别是在动画插值方面。

  • 相比欧拉角,它的优势是:

    1. 避免万向节死锁 (Gimbal Lock): 四元数不存在这个问题,可以平滑地表示任何旋转。
    2. 平滑插值: 可以通过球面线性插值 (Slerp) 实现两个方向间最短路径、恒定速度的平滑过渡,这对于动画至关重要。欧拉角的插值效果则非常不稳定。
  • 相比旋转矩阵,它的优势是:

    1. 更紧凑: 只需要4个浮点数(相比矩阵的9个或16个),节省内存。
    2. 更高效: 组合多个旋转(四元数乘法)比矩阵乘法计算量小。
    3. 数值更稳定: 浮点数误差累积效应更小。

二、 四元数的数学背景 (The "What")

  • 核心观点: 四元数是复数的扩展,它有一个实部三个虚部。在图形学中,我们通常将它看作一个四维向量,其中实部和虚部的向量部分共同编码了一个三维旋转。

  • 定义与结构:

    • 一个四元数 可以表示为 ,其中:
      • 虚部 (Vector Part),可以看作一个3D向量。
      • 实部 (Real Part),一个标量。
    • 完整的数学形式为:
  • 核心运算 (Core Operations):

    • 乘法: 四元数乘法不满足交换律 ()。其公式结合了向量的点积和叉积,这也是它能表示旋转的奥秘所在。
    • 共轭 (Conjugate) : 仅将虚部(向量部分)取反。
    • 模长 (Norm) : 把它当作一个四维向量求长度。
    • 逆 (Inverse) :
  • 单位四元数 (Unit Quaternion) - [最重要的类型]:

    • 核心特性: 模长为1的四元数 ()。它们是所有3D旋转的数学载体。
    • 关键优化: 对于单位四元数,其逆等于其共轭 ()。这使得求逆运算变得极其廉价!
    • 几何表示: 任何单位四元数都可以用旋转轴 旋转角 来表示: 这是连接抽象数学与直观几何的桥梁。

三、 四元数变换与应用 (The "How")

  • 核心观点: 单位四元数通过一个“三明治”式的乘法来对点或向量进行旋转,并且可以轻松地与其他变换(如其他四元数或矩阵)组合。

核心旋转操作

  • 旋转公式: 要用单位四元数 旋转一个点 (表示为纯虚四元数 ),使用以下公式:
  • 角度加倍: 如果一个单位四元数由轴 和角度 构成,即 ,那么它实际执行的旋转是绕轴 旋转

变换的连接与转换

  • 连接 (Concatenation): 连续进行两次旋转(先用 ,后用 ),等效于使用一个新的四元数 进行旋转。这比矩阵乘法快得多。
  • 四元数 矩阵: 存在直接的转换公式,可以将四元数转换为一个等效的 旋转矩阵,以便在渲染管线中使用。这个转换过程不涉及任何三角函数,非常高效。
  • 矩阵 四元数: 也可以将纯旋转矩阵转换回四元数。通常通过计算矩阵的迹 (Trace) 来求解 ,进而求解其他分量。实现时需要注意处理数值稳定性问题。

球面线性插值 (Slerp) - 四元数的核心优势

  • 核心观点: Slerp 可以在两个方向(由单位四元数 表示)之间,沿着4D单位超球面上的最短弧线(测地线, Geodesic)进行平滑、匀速的插值。
  • 应用: 这是实现角色骨骼、相机平滑运动等各种游戏动画的关键。
  • Slerp 公式: 其中 是两个四元数在4D空间中的夹角,可以通过 求得。
  • Squad (球面四元数样条): 当需要在多个关键帧方向之间创建平滑曲线时,可以使用 squad,它类似于点的样条曲线,可以保证路径的 C1 连续性(速度连续)。

将一个向量旋转到另一个向量

  • 核心问题: 计算一个旋转,能将单位向量 对准单位向量 。这是一个在AI朝向、程序化动画中极其常见的任务。
  • 高效解法: 可以利用 的点积和叉积,直接构建出所需的旋转四元数 ,甚至可以直接推导出最终的旋转矩阵。
  • 优势: 相比于欧拉角或传统的轴角旋转方法,这种基于四元数的推导出的最终公式不含任何三角函数或开方运算,执行效率极高。

总结与实践建议

  • 忘记欧拉角插值,拥抱 Slerp。这是你使用四元数能获得的最大收益。
  • 当你需要组合多个旋转时,优先使用四元数乘法,最后再把结果转换成矩阵(如果需要的话)。
  • 在引擎中,物体的 Transform 组件通常会同时存储位置(Vector3)、旋转(Quaternion)和缩放(Vector3),在需要时才组合成一个完整的变换矩阵。
  • 虽然数学看起来复杂,但现代游戏引擎(Unity, Unreal Engine)和数学库(GLM, Eigen)已经为你封装好了所有这些操作。你的任务是理解哪个函数用在哪个场景,以及它背后的几何意义和性能特点

掌握四元数,你便掌握了现代实时渲染中物体姿态控制的精髓。


我们继续深入第四章的后半部分。这部分内容将从角色动画的核心技术(顶点混合与变形)过渡到将整个三维世界呈现到二维屏幕上的最后一步——投影。这些都是你在引擎开发中每天都会接触到的实用技术。


角色动画技术 (Character Animation Techniques)

当处理角色、生物等非刚性物体时,我们需要更高级的动画技术来模拟柔软、平滑的运动。

4.4 顶点混合 (Vertex Blending) / 蒙皮 (Skinning)

  • 核心观点: 顶点混合是一种通过骨骼 (Skeleton) 来驱动模型表面(蒙皮, Skin)变形的技术,从而实现流畅、自然的关节弯曲效果,是现代角色动画的基石。

  • 关键术语:

    • 骨骼 (Skeleton/Bones): 一套内置于模型内部的、具有层级关系的变换节点。动画师通过驱动骨骼运动来间接控制模型。
    • 蒙皮 (Skinning): 将模型网格的顶点“附着”到骨骼上的过程。
    • 权重 (Weights): 每个顶点都可以被一或多个骨骼影响,权重 () 代表了第 根骨骼对该顶点的影响程度。对于单个顶点,所有影响它的权重之和通常为1。
  • 工作原理 (线性蒙皮混合, Linear-Blend Skinning):

    1. 在初始姿势(Bind Pose)下,为每个顶点指定影响它的骨骼及对应的权重。
    2. 在每一帧动画中,骨骼会根据动画数据移动到新的位置。
    3. 对于每一个顶点,分别计算它在每根相关骨骼的变换矩阵作用下的新位置。
    4. 最终,该顶点的最终位置是这些新位置的加权平均值
  • 核心公式:

    • : 顶点的原始模型空间坐标。
    • : 初始姿势矩阵的逆,作用是把顶点从模型空间转换到第 根骨骼的局部空间。
    • : 第 根骨骼在当前动画时刻 的世界变换矩阵。
    • : 这两项的组合,是将顶点从原始模型空间直接变换到骨骼驱动后的最终世界空间的复合矩阵。
    • : 权重。
  • 性能优势: 这种技术对 GPU 非常友好。模型的几何体数据(顶点、索引等)可以作为静态数据一次性上传到 GPU。之后每一帧,CPU 只需要更新骨骼的变换矩阵(数据量很小),然后在 Vertex Shader 中为每个顶点执行顶点混合计算。

  • 缺点与改进:

    • 线性混合的缺陷: 在关节处弯曲过度时,会出现体积损失(如“面条手”)、不自然的折叠和“糖纸”般的扭曲。
    • 双四元数混合 (Dual Quaternion Blending): 一种更先进的技术,能更好地保持关节处的体积,避免扭曲,效果更佳。它的计算成本略高于线性混合,但已被广泛采用。

4.5 变形 (Morphing)

  • 核心观点: 通过在多个预设的模型形状之间进行插值,来实现模型形状的平滑过渡。常用于制作角色面部表情、肌肉变化等。

  • 关键术语:

    • 变形目标 (Morph Target) / 混合形状 (Blend Shape): 这是变形技术中最常用的一种,基于一个基础模型和多个目标形状进行混合。
  • 工作原理 (Blend Shapes):

    1. 准备素材: 创建一个中性模型 (Neutral Model) (如无表情的脸)和若干个目标姿态 (Target Poses) (如微笑、惊讶等)。这些模型必须拥有完全相同的顶点数量和拓扑结构。
    2. 预计算差值: 计算出每个目标姿态相对于中性模型的顶点位移差值向量
    3. 实时混合: 在运行时,最终的模型形状 由中性模型加上所有目标姿态差值的加权和得到。
    • 通过实时调整权重 ,动画师可以自由组合出成千上万种细腻的表情。权重甚至可以是负数,以产生与目标姿态相反的效果(例如,微笑的权重为-1,可能变成皱眉)。
  • 组合技术: 姿态空间变形 (Pose-Space Deformation) 等技术将顶点混合(用于骨骼驱动的身体动画)和变形目标(用于表情动画)结合起来,实现完整且生动的角色表演。

4.6 几何缓存回放 (Geometry Cache Playback)

  • 核心观点: 对于无法通过骨骼或变形实时计算的超高质量动画(如流体模拟、布料解算),可以预先计算并录制每一帧的顶点数据,然后在运行时像播放视频一样“回放”这些数据。
  • 挑战: 未经压缩的几何缓存数据量极为庞大,会产生巨大的内存和带宽瓶颈。
  • 解决方案 (压缩):
    • 量化 (Quantization): 降低数据精度,如用16位整数代替32位浮点数。
    • 时域/空域预测编码: 不存储每个顶点的绝对位置,而是存储它与“预测位置”的差值。预测越准,差值越小,数据越容易压缩。这与视频压缩(如MPEG)的原理类似。

投影变换 (Projection)

投影是 3D 渲染管线的最后一步变换,它定义了观察者如何“看”到 3D 世界,并将 3D 场景坐标转换到 2D 屏幕坐标的准备阶段。

  • 核心观点: 投影变换的目的是将一个被称为视景体 (View Volume) 的三维空间区域,“压扁”并“拉伸”成一个标准的、边长为2的立方体,这个立方体被称为规范观察体 (Canonical View Volume, CVV)
  • 关键术语:
    • 齐次裁剪空间 (Homogeneous Clip Space): 顶点经过投影矩阵变换后所处的空间。
    • 规范化设备坐标 (Normalized Device Coordinates, NDC): 齐次裁剪空间中的坐标经过齐次除法(所有分量除以w分量)后得到的坐标,其范围在 CVV 内部。
    • CVV 约定:
      • OpenGL: [-1, 1] 范围在 x, y, z 所有轴上。
      • DirectX: [-1, 1] 在 x, y 轴上,但 [0, 1] 在 z 轴上。

4.7.1 正交投影 (Orthographic Projection)

  • 核心特性: 平行线在投影后仍然平行,物体的大小不会随距离而改变。适用于 2D 游戏、工程制图或某些风格化的 3D 游戏(如《纪念碑谷》)。
  • 工作原理: 将一个由 (左, 右, 下, 上, 近, 远) 六个平面定义的长方体视景体,通过平移缩放,映射到 CVV。
  • 矩阵形式: 是一个缩放矩阵和一个平移矩阵的组合。

4.7.2 透视投影 (Perspective Projection)

  • 核心特性: 模拟人眼视觉,具有“近大远小”的效果。平行线在地平线上会汇聚于一点。这是绝大多数 3D 游戏使用的投影方式。

  • 工作原理:

    • 它将一个视锥体 (Frustum)(一个被切掉顶部的金字塔)映射到 CVV。
    • 其数学魔法在于,它会修改顶点的w分量。变换后的 w 值与原始顶点的深度(距离相机的远近)成正比。
    • 在后续的齐次除法(硬件自动完成)中,x, y, z 分量都会被 w 除。因此,距离越远的顶点(w值越大),其最终的 NDC 坐标值就越小,从而在屏幕上看起来更小。
  • 视场角 (Field of View, FOV): 定义了相机视野的开阔程度,是控制透视感强弱的关键参数。

  • 深度精度问题 (Depth Precision):

    • 问题: 标准的透视投影会导致深度缓冲(Z-Buffer)的精度在深度方向上非线性分布。大部分精度集中在近裁剪平面附近,而远处的物体精度极低,容易导致 Z-Fighting(深度冲突,表现为表面闪烁)。
    • 原因: 变换后的 NDC 深度 与视点空间深度 反比关系 ()。
    • 现代解决方案: 反向 Z-Buffer (Reversed Z):
      • 通过修改投影矩阵,将近平面映射到 NDC 的 z=1,远平面映射到 z=0
      • 当与浮点数深度缓冲结合使用时,这种方法可以极大地改善深度精度在整个视锥体内的分布,有效解决 Z-Fighting 问题,是当今主流引擎的标准实践。