概念页
投影矩阵
Projection Matrix
投影矩阵把视景体变换到规范视体(OpenGL 为 ,DirectX 的 z 为 ),在那里裁剪更高效。正交投影保持平行线平行、物体大小与距离无关;透视投影让远处变小,产生的深度与观察深度成反比,近平面位置和"反向 z"决定深度精度。
从相机空间到屏幕,透视除法发生在裁剪坐标(clip)变成 NDC 的那一步。
flowchart LR Cam["相机空间"] --> Clip["裁剪坐标 clip:投影矩阵乘完"] Clip --> Div["透视除法 ÷w"] Div --> NDC["NDC 规范立方体"] NDC --> Scr["视口变换 → 屏幕像素"]
正交投影
- 最简单的形式把 z 置 0,不可逆,且会把相机前后的点都投到平面上。
- 常用形式由 定义的 AABB 先平移到原点再缩放:,,。
- 因为沿 看,。用户习惯输入"近小远大",可以在内部取负。
- 由于 ,正交矩阵总是包含一次镜像,把右手观察坐标转成左手的规范化设备坐标 (NDC)。 正交不改变平行线、也不靠 做透视缩短;透视把深度写进 ,齐次化后远处变小、平行线汇聚。
flowchart TD
In["相机空间图元"] --> Kind{"投影类型"}
Kind -->|"正交"| Orth["平行线保持平行;w 通常恒为 1"]
Kind -->|"透视"| Pers["平行线汇聚于灭点;结果 ÷w 后远处缩小"]
Orth --> NDC1["映射到 NDC"]
Pers --> NDC2["映射到 NDC"]- DirectX 再乘一个把 z 从 映射到 的缩放平移矩阵;其文档中矩阵以转置形式出现(行向量记法)。
透视投影
投影到平面 :由相似三角形 ,对应矩阵最后一行为 ,结果除以 。
更常用的是把视锥 () 变换到规范视体。OpenGL 形式( 以正值输入,仍代表 方向距离):
- 只给垂直视野 、宽高比 时,左上两项为 与 ,(即旧的 gluPerspective)。
- DirectX 把近平面映射到 0、远平面到 1,且使用左手系(看向 )。
- 远平面可以取到无穷远,得到另一种矩阵(Eq. 4.73)。
- 非对称视锥( 或 )用于立体显示和 VR。
视野角
- 例:约 22 英寸宽的 25 英寸显示器,12 英寸外观看时水平视野 85°,20 英寸 58°,30 英寸 40°;35mm 相机配 50mm 镜头,。
- 视野比物理设置窄:透视效果减弱,像放大。更宽:物体失真(像广角镜头),屏幕边缘尤甚,近处物体尺度被夸大;但会让物体显得更宏大,并给玩家更多周围信息。
深度精度
- ( 为矩阵常数),与输入深度成反比。例: 时, 位于中点 60 处的 NDC 深度是 0.833 而非 0。
- 近平面离原点越近,远处可用的 NDC 深度区间越小,z-buffer 在远处精度越差。
- 反向 z:存储 。Reed 的模拟表明浮点深度缓冲配合反向 z 精度最好,整数深度缓冲(通常 24 位)也推荐这样做。 标准映射下 NDC 深度与观察深度成反比,精度挤在近处;反向 z 把更多浮点精度留给远处。
flowchart LR Near["近处几何"] -->|"标准 z"| Dense["NDC 深度码密集"] Far["远处几何"] -->|"标准 z"| Sparse["NDC 深度码稀疏 → 易 z-fighting"] Far2["远处几何"] -->|"反向 z"| Better["落在精度更好的浮点区间"]
- 不反向时,把投影矩阵与其他变换分开乘( 优于预先合成的 )可降低误差。在 区间 fp32 和 int24 精度相近(fp32 有 23 位尾数)。
- 的原因是硬件更简单、深度压缩更有效。
其他提高深度精度的方法
- 对数深度:在顶点着色器中重映射 (Kemen 的公式),也可逐片元计算——在没有浮点深度、深度范围很大时是好选择;逐顶点做时三角形需要足够细分,否则线性插值与真实值偏差大。
- 用上一帧 z-buffer 确定最大近平面和最小远平面。
- 多视锥:沿深度把视锥切成多个子视锥,从后往前逐个渲染,每个子视锥前清空深度缓冲,可达到任意精度。
取舍与常见坑
| 问题 | 原因 | 处理 |
|---|---|---|
| 远处 z-fighting | 近平面太近,深度分布倒数化 | 推远近平面、反向 z、浮点深度、对数深度或多视锥 |
| OpenGL 与 DirectX 结果不同 | z 范围、手性、矩阵记法不同 | 使用对应 API 的矩阵 |
| 广角画面边缘拉伸 | 视野角远大于物理观看角 | 让视野接近实际观看几何 |
PBRT 的视角:光线追踪器里的投影矩阵(PBRT 4e 5.2)
- 只用来生成光线:光栅化必须剔除近平面前的物体(避免深度 0 处的奇点和把相机后方的点投到前方),而光线追踪器只用投影矩阵生成相机光线,近、远平面的取值几乎无关紧要,上文关于深度精度和反向 z 的讨论在这里都不适用。
- pbrt 的约定:左手系,相机看 ;屏幕空间里近平面 、远平面 (与 DirectX 的 NDC 深度范围相同,但 x、y 的处理不同);NDC 空间的 从左上角 到右下角 ;光栅空间同 NDC,只是 以像素计。屏幕到光栅要翻转 ,因为屏幕空间 向上、光栅空间向下。注意 pbrt 的"NDC"与上文 OpenGL/DirectX 的规范立方体不是一回事。
- 正交:先平移使近平面到 ,再在 上缩放使远平面到 , 不变。对光线追踪来说,近平面在 0 正好让光线从过相机位置的平面出发。相机空间中光线方向恒为 ,像素偏移只改变原点,所以光线微分可以预先算好。
- 透视:
再乘 的缩放,使视野内的点落在 ;非方形图像较窄的一边映射到 ,较宽的一边按比例更大(RTR4 则用垂直视野和宽高比 、)。透视相机的光线都从原点出发,方向直接取近平面上的点坐标,省去一次减法。另预存相机视锥的最大夹角余弦
cosTotalWidth(指向图像角并计入滤波器半径),可用一次点积剔除视野外的点。 - 相机接口的其他职责(PBRT 5.1):
GenerateRay()返回的方向必须归一化;SampleTime()把 的均匀样本线性映射到快门开启—关闭区间,对时间做点采样即得运动模糊。CameraBase::GenerateRayDifferential()通过多次调用GenerateRay()求偏移一个像素的光线:、 方向各先试前向差分、失败再试后向差分,因为真实镜头在图像边缘有暗角,主光线有效时偏移光线可能落到镜头成像范围之外;任一方向失败,主光线照常追踪,只是没有微分。 - 球面相机(PBRT 5.3):
SphericalCamera不继承ProjectiveCamera,支持等距柱状( 从图像顶部 0 到底部 , 从左到右 0 到 )和等面积两种映射;两种映射都以 为"上",而相机空间以 为上,所以映射后交换 、。像素滤波器会让 略超出 ,等面积映射先用WrapEqualAreaSquare()处理边界。等面积映射也是ImageInfiniteLight使用的格式,所以球面相机渲染的图可以直接当环境光源。 - 非线性投影(如球面相机的经纬度或等面积映射,见 球面几何与方向参数化)不能用一个 4×4 矩阵表示,这正是光线追踪相对光栅化的灵活之处:光栅化依赖"直线投影后仍是直线",光线追踪不需要。
出处
- realtime_rendering_4ed.pdf 第 4 章 Transforms
- PBRT 4e source excerpt: chapter 05 (Cameras and Film)
- Pharr, Jakob, Humphreys《Physically Based Rendering: From Theory to Implementation》第 4 版(MIT Press, 2023)第 5 章 5.2–5.3 节,pbr-book.org/4ed/Cameras_and_Film
相关页面
图形学坐标空间Coordinate Spaces顶点从模型到屏幕要依次经过模型空间、世界空间、观察空间、裁剪空间、标准化设备坐标 (NDC)、窗口坐标。每一步变换都有明确目的,大部分可以用 4×4 矩阵表示并相乘合并。游戏数学齐次坐标与矩阵约定Homogeneous Coordinates & Matrix Conventions实时渲染用 4×4 矩阵和四元素齐次坐标统一表示点和方向:方向向量 w=0,点 w=1。这样线性变换与平移可以合成为仿射变换并连乘。RTR4 采用列向量记法、右手观察坐标系;DirectX 采用行向量记法,书中强调这只是记法差异。图形学深度缓冲Z-Buffer深度缓冲是几乎所有图形硬件用来解决可见性的算法:为每个像素存一个当前最近图元的深度值,新片元更近才写入颜色和深度。它简单、和图元数量成线性关系、允许大多数图元以任意顺序绘制,但不能直接处理半透明。图形学阴影贴图Shadow Mapping阴影贴图 (Williams, 1978) 先从光源位置渲染深度,再从相机渲染时把每个点到光源的距离与贴图中存的深度比较:更远就在阴影中。它开销可预测(生成约与图元数成线性、查询为常数时间),非常适合 GPU,是任意表面阴影最常用的算法。主要问题是分辨率、深度精度带来的混叠、阴影痤疮和漏光。图形学雾与简易体积光照Fog & Simple Volumetric Lighting这类"老派"技巧依赖经验模型,但至今仍然好用:深度雾、高度雾和局部雾体积用透射率混合雾色;光柱可用拉伸的面向相机粒子、单次散射的解析积分、平面切片,或屏幕空间径向模糊实现(RTR4 14.2 节)。图形学VR 与 AR 显示基础VR & AR Display Fundamentals虚拟现实 (VR) 完全替换用户所见的世界,增强现实 (AR) 把合成物体融入真实世界,二者常合称 XR。本页介绍与渲染相关的硬件与物理要素:追踪与显示设备、"动作到光子"延迟及其导致的模拟器晕动症、姿态预测、镜头光学畸变与色差的软件补偿、滚动与全局显示,以及立体视觉中的辐辏-调节冲突与瞳距。这些约束决定了 VR 渲染为何必须高帧率、低延迟并严格依赖厂商 SDK。游戏数学视锥相交测试View Frustum Intersection Tests层次视锥剔除遍历 BVH 时最频繁调用的就是视锥与包围体的测试,理想结果分三态:完全在外(剪掉子树)、完全在内(子树免测)、相交(递归)。本页讲从组合矩阵直接提取六个视锥平面、把"BV 对视锥"转化为"点对扩张/收缩体积"的推导思路,以及视锥-球、视锥-盒的高效保守测试及其误报情况。图形学硬件深度剔除与纹理单元Hardware Depth Culling & Texture UnitsGPU 的深度管线先在瓦片级用 HiZ 单元做 zmax/zmin 粗剔除,再逐采样做 early-z 深度测试以免执行被遮挡片元的像素着色器,必要时退回到着色后的 late depth test;深度缓冲同样有瓦片压缩与快速清除。纹理单元以固定功能硬件完成寻址、过滤、钳位与解压(比软件快可达 40 倍),按 quad 有限差分求导数以选择 LOD,并依靠瓦片化/Morton 交织存储和纹理缓存提高局部性。图形学阴影基础与阴影体Shadow Basics & Shadow Volumes阴影帮助玩家判断物体的位置。精确光源只产生硬阴影,面光源产生带本影和半影的软阴影。最简单的情况是投射到平面上的投影阴影;投影纹理可把阴影扩展到曲面;阴影体用模板缓冲计数,能在任意表面得到精确硬阴影,但开销极不稳定,如今很少使用。图形学局部反射探针Localized Reflection Probes镜面全局光照需要高角分辨率但只关心反射方向附近的小立体角。实时中最流行的方案是在场景中稀疏放置局部环境贴图(反射探针),配合反射代理体做视差校正;它实现简单、快、美术可控,但有拉伸和漏光问题。另有体素锥追踪和平面反射等替代方案(RTR4 11.6–11.6.4 节)。游戏开发 · UE5相机系统Camera System传统相机链路是:PlayerController 持有 PlayerCameraManager,后者维护一个视图目标 (view target),通过 CalcCamera 取得相机组件或 Actor 的位置朝向,并在不同目标之间混合。实验性的 Gameplay Camera System 把相机行为做成数据资产:一个 Camera Asset 包含多个由节点网络构成的 Camera Rig、进出转换,以及决定当前使用哪个 Rig 的 Camera Director。游戏策划游戏镜头Game Camera糟糕的镜头是让玩家最快弃游的原因。Rogers 把镜头作为"三个 C"的第二个:先选一种主镜头(静态、可卷动、视差卷动、第一人称、第三人称跟随、2.5D、等距、俯视、AR),其他镜头只用于特定情境;再决定玩家是否掌控镜头;最后借用电影的景别、角度、运镜与构图规则,并守住两条铁律——镜头永远指向目标、永远不让角色离开镜头(Level Up! 第 3 版 Level 6 The Three Cs, Part 2: Camera,p.139–167)。游戏数学球面几何与方向参数化Spherical Geometry & Direction Parameterizations渲染中大量计算发生在单位球面上:方向就是球面上的点,一组方向就是球面上的一块区域。本页按 PBRT 4e 3.8 节整理立体角、球面多边形面积、三种球面参数化(球坐标、八面体编码、等面积映射)以及用于剔除光源的方向锥,并附原书一处公式问题。