GAMES101 04
前言
这节课整体的核心逻辑只有四步,简称为MVP 变换:
Model(模型变换): 把物体摆放到三维世界中的合适位置。
View(视图/相机变换): 把相机摆到标准原点,调整观察视角。
Projection(投影变换): 把三维场景“缩放压扁”到标准立方体中(为绘制到二维屏幕做准备)。
Viewport(视口变换): 把标准立方体映射到真实的屏幕像素上(第五讲内容)。
下面为你整理了第四讲的超详细笔记与核心公式推导,帮助你把每一个难点彻底搞懂!
一、 3D 变换与齐次坐标 (3D Transformations)
1. 3D 齐次坐标
从 2D 扩展到 3D,只需要增加一个 $z$ 轴:
3D 点: $(x, y, z, 1)^T$
3D 向量: $(x, y, z, 0)^T$
如果 $w \neq 0$,齐次坐标 $(x, y, z, w)^T$ 表示三维空间中的点 $(\frac{x}{w}, \frac{y}{w}, \frac{z}{w}, 1)^T$。
2. 3D 旋转矩阵的“小陷阱”
3D 中的平移和缩放非常直观(对角阵加 $t_x, t_y, t_z$),但旋转有一个极其关键的细节:
绕 X 轴和 Z 轴旋转的形式是一致的,但绕 Y 轴旋转矩阵的负号位置刚好相反
绕 X 轴旋转 $\alpha$:
$$R_x(\alpha) =
\begin{pmatrix}
1 & 0 & 0 & 0 \cr
0 & \cos\alpha & -\sin\alpha & 0 \cr
0 & \sin\alpha & \cos\alpha & 0 \cr
0 & 0 & 0 & 1
\end{pmatrix}
$$绕 Y 轴旋转 $\beta$(负号在右上角):
$$R_y(\beta) =
\begin{pmatrix}
\cos\beta & 0 & \mathbf{\sin\beta} & 0 \cr
0 & 1 & 0 & 0 \cr
\mathbf{-\sin\beta} & 0 & \cos\beta & 0 \cr
0 & 0 & 0 & 1
\end{pmatrix}
$$绕 Z 轴旋转 $\gamma$:
$$R_z(\gamma) =
\begin{pmatrix}
\cos\gamma & -\sin\gamma & 0 & 0 \cr
\sin\gamma & \cos\gamma & 0 & 0 \cr
0 & 0 & 0 & 1 \cr
0 & 0 & 0 & 1
\end{pmatrix}
$$
为什么绕 Y 轴旋转的负号颠倒了?
因为根据右手定则,基向量乘积是 $X \times Y = Z$,$Y \times Z = X$,但 $Z \times X = Y$。在计算 Y 轴时,右手系的基向量交叉顺序是 $Z \to X$,而 X 轴和 Z 轴都是 $X \to Y$ 和 $Y \to Z$。
3. 欧拉角与罗德里格斯公式
欧拉角 (Euler Angles): 任何复杂的 3D 旋转都可以拆解为依次绕 X、Y、Z 轴旋转:$R_{xyz}(\alpha, \beta, \gamma) = R_x(\alpha) R_y(\beta) R_z(\gamma)$(即航模/飞行器中的 Pitch 俯仰, Yaw 偏航, Roll 翻滚)。
罗德里格斯旋转公式 (Rodrigues’ Rotation Formula): 如果要绕任意方向的轴 $\vec{n}$ 旋转 $\alpha$ 角,不需要拆成 XYZ 轴,直接使用罗德里格斯公式即可算出对应的 $3\times3$ 旋转矩阵。
二、 视图/相机变换 (View / Camera Transformation)
核心直觉: 拍照时,是相机动还是世界动?在数学上,让相机固定在原点,把整个世界往相反方向拉,效果完全一样
1. 定义相机三要素
一个摄像机在三维空间中的状态由三个向量决定:
位置 (Position $\vec{e}$):相机在哪?
观察方向 (Look-at / Gaze direction $\vec{g}$):相机朝哪看?
向上方向 (Up direction $\vec{t}$):相机的顶部朝哪(决定相机是否颠倒或倾斜)?
2. 标准相机位置 (Canonical Camera)
为了简化后续计算,图形学规定标准相机位置为:
位置位于原点 $(0,0,0)$
观察方向指向 $-Z$ 轴
向上方向指向 $+Y$ 轴
3. 视图变换矩阵 $M_{view}$ 的推导(逆向思考技巧)
我们需要找到一个变换矩阵 $M_{view}$,把任意位置的相机“拉”到标准位置。这个变换由平移和旋转组成:
$$M_{view} = R_{view} \cdot T_{view}$$
平移矩阵 $T_{view}$: 把相机位置 $\vec{e}$ 平移到原点 $(0,0,0)$。
$$T_{view} =
\begin{pmatrix}
1 & 0 & 0 & -e_x \cr
0 & 1 & 0 & -e_y \cr
0 & 0 & 1 & -e_z \cr
0 & 0 & 0 & 1
\end{pmatrix}
$$旋转矩阵 $R_{view}$:
直接求“任意方向 $\to$ 标准方向”的旋转矩阵很难,但求它的逆过程(标准方向 $\to$ 任意方向)极度简单
逆旋转矩阵 $R_{view}^{-1}$ 会把:
$(1,0,0)^T \to \vec{g} \times \vec{t}$ (右方向)
$(0,1,0)^T \to \vec{t}$ (上方向)
$(0,0,1)^T \to -\vec{g}$ (后方向,因为相机朝 $-Z$ 看)
写出逆矩阵:
$$R_{view}^{-1} = \begin{pmatrix} x_{\vec{g}\times\vec{t}} & x_t & x_{-g} & 0 \cr y_{\vec{g}\times\vec{t}} & y_t & y_{-g} & 0 \cr z_{\vec{g}\times\vec{t}} & z_t & z_{-g} & 0 \cr 0 & 0 & 0 & 1 \end{pmatrix}$$
因为旋转矩阵是正交矩阵,正交矩阵的逆矩阵等于其转置矩阵!所以直接取转置:
$$R_{view} = (R_{view}^{-1})^T = \begin{pmatrix} x_{\vec{g}\times\vec{t}} & y_{\vec{g}\times\vec{t}} & z_{\vec{g}\times\vec{t}} & 0 \cr x_t & y_t & z_t & 0 \cr x_{-g} & y_{-g} & z_{-g} & 0 \cr 0 & 0 & 0 & 1 \end{pmatrix}$$
三、 投影变换 (Projection Transformation)
投影有两种:正交投影 (Orthographic Projection) 和 透视投影 (Perspective Projection)。
1. 正交投影 (Orthographic Projection)
特点: 平行线保持平行,没有“近大远小”。常用于建筑 CAD 图纸、工程图、像素风游戏。
数学目标: 把空间中的一个长方体包围盒 $[l, r] \times [b, t] \times [f, n]$ 映射到标准立方体 (Canonical Cube) $[-1, 1]^3$ 中。
(注:在右手坐标系中,相机朝 $-Z$ 看,因此近平面 $n$ 的 $z$ 值大于远平面 $f$ 的 $z$ 值,即 $n > f$)。
算法步骤:
将长方体中心平移到原点;
将长方体各边长缩放到长度为 2。
正交投影矩阵 $M_{ortho}$:
$$M_{ortho} = \begin{pmatrix} \frac{2}{r-l} & 0 & 0 & 0 \cr 0 & \frac{2}{t-b} & 0 & 0 \cr 0 & 0 & \frac{2}{n-f} & 0 \cr 0 & 0 & 0 & 1 \end{pmatrix} \begin{pmatrix} 1 & 0 & 0 & -\frac{r+l}{2} \cr 0 & 1 & 0 & -\frac{t+b}{2} \cr 0 & 0 & 1 & -\frac{n+f}{2} \cr 0 & 0 & 0 & 1 \end{pmatrix}$$
2. 透视投影 (Perspective Projection)——最难也是最重要的点!
特点: 满足现实视觉“近大远小”,平行线在无穷远处相交于一点。相机的视野是一个四棱台,称为视锥体 (Frustum)。
闫老师的方法: “先把视锥体‘压扁’成长方体,再做一次正交投影”
$$M_{persp} = M_{ortho} \cdot M_{persp \to ortho}$$
关键步骤:如何推导“压扁”矩阵 $M_{persp \to ortho}$?
假设视锥体内部一点为 $(x, y, z)$,压扁后变成了 $(x’, y’, z’)$:
利用相似三角形求 $x’$ 和 $y’$:
从侧面看,根据相似三角形:
$$\frac{y’}{y} = \frac{n}{z} \implies y’ = \frac{n}{z} y$$
同理,从上面看:
$$x’ = \frac{n}{z} x$$
写成齐次坐标形式:
点坐标的变化:
$$\begin{pmatrix} x \cr y \cr z \cr 1 \end{pmatrix} \Rightarrow \begin{pmatrix} \frac{n}{z}x \cr \frac{n}{z}y \cr \text{未知} \cr 1 \end{pmatrix} \quad \text{全乘以 } z \Rightarrow \begin{pmatrix} nx \cr ny \cr \text{未知} \cdot z \cr z \end{pmatrix}$$
这意味着压扁矩阵乘以原点坐标,前两行和第四行已经确定:
$$M_{persp \to ortho} = \begin{pmatrix} n & 0 & 0 & 0 \cr 0 & n & 0 & 0 \cr ? & ? & ? & ? \cr 0 & 0 & 1 & 0 \end{pmatrix}$$
利用两个特殊条件求第三行 $(A, B)$:
条件一:近平面 $z = n$ 上的所有点,压扁后 $z$ 轴坐标完全不变。
代入 $z = n$:
$$\begin{pmatrix} 0 & 0 & A & B \end{pmatrix} \begin{pmatrix} x \cr y \cr n \cr 1 \end{pmatrix} = n^2 \implies An + B = n^2$$
条件二:远平面 $z = f$ 上的中心点 $(0, 0, f)$,压扁后 $z$ 轴坐标也不变。
代入 $z = f$:
$$Af + B = f^2$$
解二元一次方程组:
$$\begin{cases} An + B = n^2 \cr Af + B = f^2 \end{cases} \implies A = n + f, \quad B = -nf$$
最终压扁矩阵 $M_{persp \to ortho}$:
$$M_{persp \to ortho} = \begin{pmatrix} n & 0 & 0 & 0 \cr 0 & n & 0 & 0 \cr 0 & 0 & n+f & -nf \cr 0 & 0 & 1 & 0 \end{pmatrix}$$
常考思考题: 视锥体被压扁成长方体的过程中,中间点的 $z$ 值是变近了还是变远了?
- 答案:变远了(即点会向远离相机的远平面方向推送)。
四、 视锥体参数:FOV 与 Aspect Ratio
在实际游戏引擎(如 Unity / Unreal)中,我们通常不需要手动传 $l, r, b, t$,而是通过两个更直观的参数定义透视视锥体:
垂直视角 (Vertical Field of View, fovY): 相机上下能看到的张角。
宽高比 (Aspect Ratio = width / height): 屏幕宽与高的比例。
两者与 $l, r, b, t$ 的转换公式为:
$t = \vert{}n\vert{} \cdot \tan\left(\frac{fovY}{2}\right)$
$b = -t$
$r = t \cdot \text{aspect}$
$l = -r$





