中EN
概念页

齐次坐标与矩阵约定

Homogeneous Coordinates & Matrix Conventions

更新于 2026-10-16 约 14 分钟线性代数矩阵齐次坐标约定PBRT

实时渲染用 4×4 矩阵和四元素齐次坐标统一表示点和方向:方向向量 w=0w=0,点 w=1w=1。这样线性变换与平移可以合成为仿射变换并连乘。RTR4 采用列向量记法、右手观察坐标系;DirectX 采用行向量记法,书中强调这只是记法差异。

为什么需要 4×4 和齐次坐标

  • 线性变换满足 f(x)+f(y)=f(x+y)f(\mathbf{x})+f(\mathbf{y})=f(\mathbf{x}+\mathbf{y}) 与 kf(x)=f(kx)kf(\mathbf{x})=f(k\mathbf{x})。缩放、旋转等三元素向量的线性变换都能用 3×3 矩阵表示。
  • 平移 f(x)=x+(7,3,2)f(\mathbf{x})=\mathbf{x}+(7,3,2) 不是线性的:作用在两个向量上再相加,会把 (7,3,2)(7,3,2) 加两次。
  • 仿射变换先做线性变换再平移,通常存成 4×4 矩阵。平移、旋转、缩放、反射、切变矩阵都是仿射的;仿射变换保持直线的平行性,但不一定保持长度与角度。(RTR4 第 4 章开头)

点与方向

实体齐次形式平移矩阵的作用
方向向量(vx,vy,vz,0)T(v_x, v_y, v_z, 0)^T不受影响,方向不能被平移
点(px,py,pz,1)T(p_x, p_y, p_z, 1)^T被平移

至此介绍的变换都保持 ww 不变、矩阵最后一行为 (0 0 0 1)(0\ 0\ 0\ 1)。透视投影是例外:变换后 ww 通常不为 1,需要齐次化(除以 ww)得到非齐次点。几何上,齐次化可以理解为把点投影到 w=1w=1 平面上。(RTR4 4.7)

点与方向的差别完全由 ww 决定:平移只作用在 w=1w=1 的点上。

flowchart TD
  In["输入四元向量"] --> W{"w 分量"}
  W -->|"w = 1 点"| Pt["经仿射变换:被旋转+缩放+平移"]
  W -->|"w = 0 方向"| Dir["经仿射变换:只被线性部分作用,平移项乘 0"]
  Pt --> Out1["结果仍为点 w=1"]
  Dir --> Out2["结果仍为方向 w=0"]

列向量与行向量

  • RTR4 用列向量:p′=Mp\mathbf{p}'=\mathbf{M}\mathbf{p},平移量在最右一列,复合矩阵 TRSp=T(R(Sp))\mathbf{TRS}\mathbf{p}=\mathbf{T}(\mathbf{R}(\mathbf{S}\mathbf{p})) 从右往左作用。
  • DirectX 等把平移放在最下一行,向量是行向量(书中称 row-major form),矩阵顺序反过来、从左往右读;DirectX 文档中的投影矩阵因此是本书矩阵的转置形式。
  • 书中强调这纯粹是记法差异:矩阵存入内存时,16 个值中最后 4 个都是三个平移量加一个 1。(RTR4 4.1.1)

列向量与行向量只是记法镜像:变换顺序对向量「最近的矩阵先作用」这一口诀两边通用。

flowchart LR
  subgraph Col["列向量约定 Mp"]
    direction TB
    C1["p"] --> C2["先 S"]
    C2 --> C3["再 R"]
    C3 --> C4["再 T"]
    C4 --> C5["写作 T R S p"]
  end
  subgraph Row["行向量约定 pM"]
    direction TB
    R1["p"] --> R2["先 S"]
    R2 --> R3["再 R"]
    R3 --> R4["再 T"]
    R4 --> R5["写作 p S R T"]
  end
  Col -.->|"矩阵互为转置"| Row

右手与左手坐标系

  • 书中假设观察者沿相机的 −z-z 轴看,yy 向上、xx 向右,这是右手系;绕 z 轴的正角度旋转为逆时针(z 轴指出纸面)。
  • DirectX 等使用左手系,观察方向为 +z+z。两种都正确,最终效果相同。
  • 投影后的视口通常是左手系(z 指入屏幕),正交投影矩阵里因此隐含一次镜像。(RTR4 4.7.1)

世界的"上"方向

  • 制造业、3D 打印、建筑和 GIS 通常 z 朝上;航空与船舶以 −z-z 为上;面向媒体的建模系统常以 y 为上,与屏幕的上方向一致。RTR4 默认 y-up。
  • 两种约定只差一个 90° 旋转(可能还有一次镜像),但不知道对方用哪种就会出问题。
  • 相机观察空间里的"上"与世界的"上"无关:俯瞰地面的相机在 y-up 世界中的上方向是 (0,0,−1)(0,0,-1),但在观察空间里依然是 y 朝上。(RTR4 4.2.1)

取舍与常见坑

  • 在不同 API 或工具间移植时,矩阵记法、手性、上方向三件事都要核对。
  • 用右下角元素 (3,3)=1/5(3,3)=1/5 也能实现均匀放大 5 倍,但必须再做齐次化,多出除法;若系统总是做除法则没有额外开销。(RTR4 4.1.3)

GEA 的视角:矩阵基础与行向量约定(卷 I 5.3)

GEA 第 5 章从游戏引擎程序员的角度讲同样的内容,但采用行向量约定,与本页上文 RTR4 的列向量约定相反。下面按 GEA 小节整理,并标出与 RTR4 的差异。

矩阵、行列式与矩阵种类(卷 I 5.3、5.3.1–5.3.2)

  • 矩阵是 m×nm\times n 的标量数组,元素记作 MrcM_{rc}(行 r、列 c),便于表示平移、旋转、缩放等变换。
  • 原书问题:GEA 开头称矩阵便于表示「平移、旋转、缩放等线性变换」。平移不是线性变换(见本页上文 RTR4 的反例),而是仿射变换;GEA 自己在 5.3.8 也说明 3×3 矩阵无法表示平移、必须借助 4×4 齐次坐标。
  • 行列式:det⁡(abcd)=ad−bc\det\begin{pmatrix}a&b\\c&d\end{pmatrix}=ad-bc;3×3 按第一行展开:det⁡(abcdefghi)=a(ei−fh)−b(di−fg)+c(dh−eg)\det\begin{pmatrix}a&b&c\\d&e&f\\g&h&i\end{pmatrix}=a(ei-fh)-b(di-fg)+c(dh-eg)。行列式为 0 时矩阵不可逆。
  • 正交矩阵 (orthogonal / orthonormal):3×3 的行、列都是两两正交的单位向量;再加 det⁡=+1\det=+1 即特殊正交矩阵,表示纯旋转。
  • 仿射矩阵:保持直线平行性与距离比例、不一定保持绝对长度和角度的 4×4 变换矩阵,是旋转、平移、缩放、切变的任意组合。

乘法、单位阵、逆与转置(卷 I 5.3.3、5.3.5–5.3.7)

  • P=AB\mathbf{P}=\mathbf{AB} 的元素是 A\mathbf{A} 的行与 B\mathbf{B} 的列的点积,要求内维相等。两个变换矩阵之积同时执行两个变换,因此可预先合并一长串变换再批量作用于大量向量;矩阵乘法因此也叫串接 (concatenation)。不满足交换律:AB≠BA\mathbf{AB}\ne\mathbf{BA}。
  • 单位阵 I\mathbf{I}:AI=IA=A\mathbf{AI}=\mathbf{IA}=\mathbf{A}。
  • 逆:AA−1=A−1A=I\mathbf{A}\mathbf{A}^{-1}=\mathbf{A}^{-1}\mathbf{A}=\mathbf{I}。并非所有矩阵可逆,但所有仿射矩阵都可逆;一般用高斯消元或 LU 分解求逆。
  • 原书问题:「所有仿射矩阵(旋转、平移、缩放、切变的组合)都可逆」不严格:含零缩放(某轴缩放因子为 0,把物体压成平面或点)的仿射矩阵行列式为 0,不可逆。仿射变换可逆当且仅当其左上 3×3 线性部分可逆(det⁡≠0\det\ne0)——这正是 GEA 5.3.1 自己给出的行列式判据。(ABC)−1=C−1B−1A−1(\mathbf{ABC})^{-1}=\mathbf{C}^{-1}\mathbf{B}^{-1}\mathbf{A}^{-1}。
  • 转置:行列互换,(ABC)T=CTBTAT(\mathbf{ABC})^T=\mathbf{C}^T\mathbf{B}^T\mathbf{A}^T。正交(纯旋转)矩阵的逆就是转置,远比一般求逆便宜;在行向量库与列向量库之间搬数据时,矩阵也要互相转置。

行向量还是列向量(卷 I 5.3.4)

  • 行向量 1×n1\times n 必须写在矩阵左边:v′=vM\mathbf{v}'=\mathbf{v}\mathbf{M};列向量写在右边:v′=Mv\mathbf{v}'=\mathbf{M}\mathbf{v}。
  • 多个变换 A、B、C 依次作用:行向量 v′=((vA)B)C\mathbf{v}'=((\mathbf{v}\mathbf{A})\mathbf{B})\mathbf{C} 从左往右读;列向量 v′T=CT(BT(ATvT))\mathbf{v}'^T=\mathbf{C}^T(\mathbf{B}^T(\mathbf{A}^T\mathbf{v}^T)) 从右往左读。记法口诀:离向量最近的矩阵最先作用。
  • GEA 选择行向量,理由是从左到右的变换顺序对英语读者最直观;并提醒读者核对所用引擎、书籍和网页的约定——向量写在矩阵左边是行向量,右边是列向量;用列向量时要把书中所有矩阵转置。
  • 与 RTR4 的对照:RTR4 用列向量(TRSp\mathbf{TRS}\mathbf{p} 从右往左),GEA 用行向量(rSRT\mathbf{r}\mathbf{S}\mathbf{R}\mathbf{T} 从左往右),两书矩阵互为转置;两书都强调这只是记法。

齐次坐标与方向向量(卷 I 5.3.8)

  • 引子:2×2 矩阵可表示二维旋转(正角度为逆时针),行向量写法 [rx′ ry′]=[rx ry][cos⁡ϕsin⁡ϕ−sin⁡ϕcos⁡ϕ][r'_x\ r'_y]=[r_x\ r_y]\begin{bmatrix}\cos\phi&\sin\phi\\-\sin\phi&\cos\phi\end{bmatrix};它其实就是绕 z 轴的三维旋转,扩成 3×3 即可。三维旋转能用 3×3 表示,平移却不能。
  • 3×3 矩阵无法表示平移:无论怎样排列 t\mathbf{t} 的分量,乘法都得不到 rx+txr_x+t_x 这样的和。改用 4×4、把 t\mathbf{t} 放在最下一行(行向量约定)、向量第四分量 w=1w=1,第一列点积即为 1⋅rx+tx⋅11\cdot r_x+t_x\cdot1;右下角为 1、第四列其余为 0,结果的 ww 仍为 1。点在齐次坐标中总有 w=1w=1;游戏引擎的大部分 3D 矩阵运算都用 4×4 矩阵与齐次四元素向量。(原书此处一句话说「与列向量 r 相乘」,与上下文的行向量写法不一致,属笔误。)
  • 方向向量 w=0w=0,与矩阵相乘时 0⋅t0\cdot\mathbf{t} 消去平移:[v 0][U0t1]=[vU 0][\mathbf{v}\ 0]\begin{bmatrix}\mathbf{U}&\mathbf{0}\\\mathbf{t}&1\end{bmatrix}=[\mathbf{v}\mathbf{U}\ 0]。平移方向向量会改变其大小,通常不是想要的。
  • 齐次到三维:(x,y,z,w)≡(x/w,y/w,z/w)(x,y,z,w)\equiv(x/w,y/w,z/w)。w=1w=1 时除法无影响;方向除以 w=0w=0 得无穷,纯方向向量就像四维齐次空间中的无穷远点——能旋转、不能平移。

4×3 矩阵(卷 I 5.3.10)

仿射 4×4 矩阵(行向量约定下)最右一列恒为 (0,0,0,1)T(0,0,0,1)^T,游戏程序员常省去这一列以节省内存,数学库中常见 4×3 仿射矩阵。

矩阵在内存中的存储(卷 I 5.3.14)

  • C/C++ 二维数组 float m[4][4] 第一个下标是行、第二个是列,列下标在内存中变化最快。
  • 两种布局:(1) 把基向量 iC,jC,kC,tC\mathbf{i}_C,\mathbf{j}_C,\mathbf{k}_C,\mathbf{t}_C 各放一行,连续存储;(2) 各放一列,跨步存储。
  • 布局 (1) 可以直接把一行当作 4 元素向量取出,并与行向量公式一致;布局 (2) 有时用于 SIMD 下的快速矩阵-向量乘法(见 SIMD 向量化)。作者遇到的多数引擎用布局 (1)。
  • 快速判断法:调用库函数构造平移 (4, 3, 2),若第 3 行(从 0 数)为 4.0f, 3.0f, 2.0f, 1.0f,则向量存于行,否则存于列。这与 RTR4「内存中最后 4 个值都是三个平移量加 1」的说法一致。

PBRT 的视角:列向量、行主序存储与随身携带的逆矩阵(PBRT 4e 3.9.1–3.9.3、3.10)

  • 记法:PBRT 与 RTR4 一样用列向量 p′=Mpp'=Mp;矩阵的各列就是原坐标系的基向量和原点变换后的位置(Mx=[m0,0 m1,0 m2,0 m3,0]TMx=[m_{0,0}\ m_{1,0}\ m_{2,0}\ m_{3,0}]^T)。下标从 0 开始,与代码对应。复合 T=ABCT=ABC 表示先 CC 后 AA。PBRT 的"延伸阅读"特别提醒:Rogers & Adams 等经典教材用行向量 pMpM,矩阵要转置——与 GEA 的行向量约定(上文)是同一个差别。
  • 同一矩阵的两种解读:"在同一标架内移动点"和"把坐标从一个标架换到另一个",两者不兼容;pbrt 的大部分用法是后者。
  • 齐次坐标只藏在变换实现里:pbrt 没有齐次点类,变换函数内部隐式补 w=1w=1(点)或 w=0w=0(向量),只有 w≠1w\ne1(第 5 章的投影变换)时才做除法。[1,3,−2,1][1,3,-2,1] 与 [−2,−6,4,−2][-2,-6,4,-2] 是同一个点。
  • 存储:SquareMatrix<4> 按行主序存(m[i][j] 是第 ii 行第 jj 列)——内存布局与列向量记法是两回事,不要混淆。Transform 同时存矩阵和逆矩阵,单精度下共 128 字节;几百万个形状往往只有几千个不同变换,所以形状只存指针,场景构建时用 InternCache 去重。求逆失败时逆矩阵填 NaN,只要不调用用到逆的方法仍可使用;能写出解析逆的变换(平移、缩放、旋转)都直接传入逆矩阵,避免通用 4×4 求逆的开销和精度损失。(AB)−1=B−1A−1(AB)^{-1}=B^{-1}A^{-1},所以复合变换的逆就是 t2.mInv * mInv。
约定RTR4GEA4PBRT 4e
向量写法列向量 MpMp行向量 pMpM列向量 MpMp
手性右手,看 −z-z左手,看 +z+z左手,看 +z+z
逆矩阵按需计算,优先用特殊结构求逆正交矩阵的逆即转置每个 Transform 都随身存逆

原书小问题(PBRT 第 3 章参考文献):RTR4 的作者之一写成 "A. Peesce",应为 A. Pesce(Angelo Pesce)。来源:https://pbr-book.org/4ed/Geometry_and_Transformations/Further_Reading 与 RTR4 封面署名(Akenine-Möller, Haines, Hoffman, Pesce, Iwanicki, Hillaire)。

  1. realtime_rendering_4ed.pdf 第 4 章 Transforms
  2. Game_Engine_Architecture_4Ed_-_Jason_Gregory.pdf
  3. Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 I 第 5 章 5.3 节(5.3.1–5.3.8、5.3.10、5.3.14)
  4. PBRT 4e source excerpt: chapter 03 (Geometry and Transformations)
  5. Pharr, Jakob, Humphreys《Physically Based Rendering: From Theory to Implementation》第 4 版(MIT Press, 2023)第 3 章 3.9–3.10 节,pbr-book.org/4ed/Geometry_and_Transformations

相关页面

游戏数学基本仿射变换Basic Affine Transforms平移、旋转、缩放、切变是摆放和变形物体的基础矩阵;它们的连乘顺序有关、但满足结合律。刚体变换的逆可以直接写出,法线要用伴随矩阵的转置(传统说法是逆转置)变换。理解这些矩阵的性质能写出更快、更正确的变换代码。游戏数学投影矩阵Projection Matrix投影矩阵把视景体变换到规范视体(OpenGL 为 [-1,1]^3,DirectX 的 z 为 [0,1]),在那里裁剪更高效。正交投影保持平行线平行、物体大小与距离无关;透视投影让远处变小,产生的深度与观察深度成反比,近平面位置和"反向 z"决定深度精度。图形学坐标空间Coordinate Spaces顶点从模型到屏幕要依次经过模型空间、世界空间、观察空间、裁剪空间、标准化设备坐标 (NDC)、窗口坐标。每一步变换都有明确目的,大部分可以用 4×4 矩阵表示并相乘合并。游戏数学视锥相交测试View Frustum Intersection Tests层次视锥剔除遍历 BVH 时最频繁调用的就是视锥与包围体的测试,理想结果分三态:完全在外(剪掉子树)、完全在内(子树免测)、相交(递归)。本页讲从组合矩阵直接提取六个视锥平面、把"BV 对视锥"转化为"点对扩张/收缩体积"的推导思路,以及视锥-球、视锥-盒的高效保守测试及其误报情况。游戏数学直线与平面求交Line & Plane Intersections本页收录 RTR4 第 22.15~22.16 节的基础几何工具:二维直线/光线/线段求交(垂直点积法与无除法的早期拒绝法)、三维直线求交与异面直线最近点,以及三个平面的交点公式(可用于求 k-DOP 等平面围成凸体的角点)。这些在游戏中常用于射线检测、二维几何、碰撞与包围体构建。图形学实时渲染Real-Time Rendering实时渲染是在计算机上快速生成图像、并让图像随用户输入即时变化的技术。RTR4 认为它由三个要素共同定义:交互性、三维空间感,以及图形加速硬件 (GPU)。游戏数学欧拉角与万向节锁Euler Angles & Gimbal Lock欧拉变换用 head(yaw)、pitch、roll 三个角度构造朝向矩阵,直观、易于用日常语言讨论,适合小角度调整和观察者朝向。但它依赖旋转顺序,两组欧拉角难以组合和插值,并且会出现万向节锁,因此更复杂的朝向处理需要四元数。游戏开发SIMD 向量化SIMD VectorizationSIMD(单指令多数据)用一条机器指令并行处理多个数据。x86 上从 MMX 发展到 SSE(128 位,4 个 float)、AVX(256 位,8 个)和 AVX-512(512 位,16 个)。GEA 用 SSE 内建函数演示:数组相加、点积、向量×矩阵、矩阵×矩阵,强调两点——避免寄存器内的水平相加(先转置数据),以及把 SIMD 寄存器看成 N 条并行的「通道 (lane)」而不只是一个 4D 向量;条件分支则用向量谓词化 (vector predication / select) 代替。游戏数学点与向量运算Points & Vector Operations游戏程序员最常用的数学是三维向量与矩阵(三维线性代数)。本页按 GEA 第 5 章整理点与向量的基础:坐标系与手性、点与方向的区别、标量乘与 Hadamard 积、加减、模长与归一化、点积与投影、叉积、伪向量与外代数,以及线性插值 (lerp)。贯穿全章的两条经验是:能在二维里想清楚的问题先在二维里想,以及能不开方就不开方。游戏数学旋转表示的比较Comparison of Rotational Representations旋转可以用欧拉角、3×3 矩阵、轴角、四元数表示,再加上平移与缩放就有 4×4(或 4×3)矩阵与 SRT(SQT)变换;更进一步还有对偶四元数。没有一种在所有场合都最好。GEA 按大小、直观性、能否直接作用于向量、能否插值、有无万向节锁比较它们,并用「参数个数 − 约束个数 = 3 个自由度」统一解释为什么它们用的浮点数不同。图形学可编程着色器与 GPU 管线Programmable Shaders & GPU PipelineGPU 把第 2 章的概念管线实现为一组硬件阶段,分为完全可编程、可配置但不可编程、完全固定三类。现代 GPU 采用统一着色器架构:各类着色器共用同一套编程模型和核心,由 GPU 自行分配负载。着色器用 HLSL、GLSL 等类 C 语言编写,输入分为 uniform 和 varying 两类。游戏美术顶点混合与蒙皮Vertex Blending & Skinning顶点混合(也叫线性混合蒙皮、enveloping、骨骼子空间变形)让一个顶点受多根骨骼的变换影响,按权重混合结果,使关节处的"皮肤"连续弯曲。它非常适合在 GPU 上执行;主要缺点是关节折叠、扭转和自相交,可用双四元数蒙皮等方法改善。游戏开发骨骼、姿势与动画片段Skeletons, Poses & Animation Clips角色动画系统的数据核心是三样东西:骨骼(关节层级)、姿势(每个关节的 SRT 变换)和动画片段(姿势随局部时间变化的采样)。GEA 把各种动画方法看成对"逐点控制表面"这一理想的不同压缩方式;骨骼蒙皮用少量关节驱动大量顶点,是今天最主流的方案(GEA4 卷 II 13.1–13.4)。游戏数学马尔可夫链与状态机概率Markov Chains & State-Machine Probability当一个随机过程可能无限进行下去(如"每次 80% 再加 1 点伤害")时,无法枚举所有结果;把它画成以概率转移的状态机,写成转移矩阵,再用列向量反复左乘矩阵(马尔可夫链 (Markov Chain)),就能得到任意回合后的状态分布、稳态、游戏时长的中位数/均值/众数;反向则可用递归把复杂局面化归为已知的简单局面。本页按 Schreiber 与 Romero 第 22 章整理(p.525–556),并核对了书中数字。

输入关键词开始搜索

滚轮或双指缩放 · 拖动平移 · 双击放大 / 还原