【空间变换】观察变换
目录+
经过 【空间变换】基本变换【空间变换】基本变换有了 [[【空间变换】齐次坐标]] 打底,就可以来看最基础的三种变换:平移、缩放、旋转。它们是模型变换(Model Transformation)的三块积木,把物体从局部空间摆放到世界空间里的正确位置、朝向和大小,靠的就是这三者的组合。 因为统一用了齐次坐标,三种变换都写成 $4\times4$ 矩阵,可以直接连乘合并,最后对每个顶点只做一次矩阵乘法。下面逐个推导,并附上在着色器里的写法。 平移变换 平移就是给每个坐标分量加上一个偏移量,借助齐次坐标的第四列实现: $$ \begin{bmatrix} 1 & 0 & 0 & x \\ 0 & 1 & 0 & y \\ 0 & 0 & 1 & z \\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} P_x \\ P_y \\ P_z \\ 1 \end{bmatrix} = (P_x + x,\ P_y + y,\ P_z + z,\ 1) $$ 对应的着色器代码: float4x4 T = float4x4( 1, 0, 0, _TransForm.x, 0, 1, 0, 的模型变换,物体已经摆放在世界空间里。接下来要换个视角看世界——把相机放到合适的位置和角度,这一步叫观察变换(View Transformation),也叫视图变换。
打个拍照的比方:先把要拍的东西摆放好,这是模型变换;再挑一个角度架好相机,这是观察变换;最后按下快门把三维场景拍成二维照片,那是后面的 【空间变换】投影变换【空间变换】投影变换经过 [[【空间变换】观察变换]],顶点已经来到以相机为原点的观察空间。投影变换要做的,是把观察空间里相机能看到的那块区域,映射到一个规整的立方体里,方便后续裁剪。这一步的矩阵叫裁剪矩阵,也叫投影矩阵。本篇沿用 Games101 的思路推导。 先把结论列在前面,推完再回看会更清楚: - 把顶点变换到裁剪空间的目的,是方便做裁剪。 - 正交相机的裁剪空间,就是一个标准立方体(CVV)。 - 推导透视投影时,我们会乘上一个观察空间的 $z$ 值($z_{view}$),这个 $z$ 最终成为裁剪空间的 $w$ 分量。 - 透视相机的裁剪,是判断坐标 $(x, y, z)$ 是否落在 $(-w, w)$ 之内。 裁剪空间 顶点从观察空间变换到裁剪空间(Clip Space,也叫齐次裁剪空间),用的就是投影矩阵。之所以要这块空间,是为了方便对图元做裁剪: - 完全落在这块空间内部的图元,保留; - 完全落在外部的,剔除; - 与边界相交的,裁剪掉超出的部分。 这块空间由视锥体(View Frustum) 决定——它是空间中一块由六个裁剪平面(Clip Planes)围成的区域,界定。
观察空间
观察空间(View Space)就是以相机原点为坐标原点建立起来的坐标系。它的三个基向量在世界空间里的取值,描述的正是相机的朝向。
按照惯例,观察空间是右手坐标系,相机看向 方向。也就是说,相机的视线方向对应的是观察空间的 轴。如果记相机位置为 、注视目标为 ,那么视线方向(gaze)指向目标,而观察空间的 轴与视线相反:
要唯一确定一个相机,需要三个量:
- 相机的位置。
- 相机看向的方向(gaze,记作 )。
- 相机向上的方向(up,记作 )。
变换思路

观察变换要做的,是把世界空间里"位置在 、看向 、向上是 "的相机,搬正到"坐标原点、看向 、向上是 "的标准位置。这可以拆成一次平移加一次旋转。
常规做法是分四步走:
- 先把相机平移到原点;
- 再把视线 旋转到 ;
- 再把 up 方向 旋转到 ;
- 再把 旋转到 。
问题是,"把任意方向旋转到坐标轴"的旋转矩阵并不好直接写出来。于是有一个简化做法:反过来求。
简化做法——先求逆问题,再求逆矩阵:
- 与其求"任意位置 → 标准位置",不如先求"标准位置 → 任意位置";
- 也就是把标准轴旋转到相机轴: 方向, 方向, 方向;
- 最后对求出的矩阵取逆。
反过来求之所以简单,是因为"把标准轴转到某组已知向量"的矩阵,直接把这几个目标向量按列摆进去就行。
平移矩阵
把相机从位置 移回原点,是一个负向平移:
旋转矩阵
按简化思路,先写出"标准轴 → 相机轴"的旋转矩阵,做法就是把三个目标向量 、、 分别作为矩阵的列。可以验证,这个矩阵作用在 上,得到的正是第一列 :
我们真正需要的是它的逆——"相机轴 → 标准轴"。这里有一条关键性质:旋转矩阵是正交矩阵,正交矩阵的逆等于它的转置。 所以直接转置就得到了观察变换所需的旋转矩阵:
合并
先平移到原点,再旋转对齐坐标轴,观察变换矩阵就是两者相乘:
顶点经过 之后就来到了观察空间。下一步是把这个视锥体里的空间投影到裁剪空间,见 【空间变换】投影变换【空间变换】投影变换经过 [[【空间变换】观察变换]],顶点已经来到以相机为原点的观察空间。投影变换要做的,是把观察空间里相机能看到的那块区域,映射到一个规整的立方体里,方便后续裁剪。这一步的矩阵叫裁剪矩阵,也叫投影矩阵。本篇沿用 Games101 的思路推导。 先把结论列在前面,推完再回看会更清楚: - 把顶点变换到裁剪空间的目的,是方便做裁剪。 - 正交相机的裁剪空间,就是一个标准立方体(CVV)。 - 推导透视投影时,我们会乘上一个观察空间的 $z$ 值($z_{view}$),这个 $z$ 最终成为裁剪空间的 $w$ 分量。 - 透视相机的裁剪,是判断坐标 $(x, y, z)$ 是否落在 $(-w, w)$ 之内。 裁剪空间 顶点从观察空间变换到裁剪空间(Clip Space,也叫齐次裁剪空间),用的就是投影矩阵。之所以要这块空间,是为了方便对图元做裁剪: - 完全落在这块空间内部的图元,保留; - 完全落在外部的,剔除; - 与边界相交的,裁剪掉超出的部分。 这块空间由视锥体(View Frustum) 决定——它是空间中一块由六个裁剪平面(Clip Planes)围成的区域,界定。