2D Transformation
在二维空间中,我们能用二维矩阵表示所有的线性变换。但二维空间中的平移在二维空间中不是线性变换,因此我们希望找到另一个空间,并将二维空间嵌入,让二维平移在这个空间中变为线性变换。把笛卡尔坐标扩展为齐次坐标,就得到了这样的空间。
对二维空间的一点 $(x,y)$,三元组 $(xZ,yZ,Z)$ 即为该点的齐次坐标。如 $(1,2)$ 可表示为 $(1,2,1)$ 或 $(100,200,100)$. 换句话说,二维空间的任何点都能表示为齐次坐标 $(X,Y,Z)$,其中 $Z\neq 0$.
另外,如果我们把无穷远点也考虑进来,我们就可以用 $(x,y,0)$ 表示无穷远点。
叽里咕噜说什么呢,快告诉我怎么用线性变换表示平移!
对二维空间的一点 $(x,y)$,首先将它转化为齐次坐标得到 $(x,y,1)$,然后与下面的矩阵相乘
就得到了 $(x+t_x,y+t_y,1)$. 然后再转换回笛卡尔坐标,就得到了 $(x+t_x,y+t_y)$.
这样一来,旋转、平移就能统一成下面的形式:
3D Transformation
与二维的情况类似,我们也把三维空间嵌入一个新空间。
对三维空间的一点 $(x,y,z)$,三元组 $(xS,yS,zS,S)$ 即为该点的齐次坐标。如 $(1,2,3)$ 可表示为 $(1,2,3,1)$ 或 $(100,200,300,100)$. 换句话说,三维空间的任何点都能表示为齐次坐标 $(X,Y,Z,S)$,其中 $S\neq 0$.
我们这里讨论右手坐标系,下面给出按右手定则旋转 $\theta$ 角度的矩阵:
你会注意到沿 $y$ 轴旋转的矩阵和别的不一样,但这是完全正确的,认真算一算就好了。
(我没感觉这里有什么“深刻含义”,但感觉即使有也应该不会很有用……)
(不过不知道如果推广到 $n$ 维旋转会不会有用)
(可我们生活在三次元!)
值得注意的是,旋转矩阵都是正交矩阵,所以它的转置就是它的逆。
世界上还存在一个叫做 Rodrigues 旋转公式的东西,它给出了向量 $v$ 绕单位向量 $k$ 旋转 $\theta$ 角度得到的结果。(按右手定则旋转)
当然也可以把这个旋转矩阵写出来:
最右边那个矩阵是 $k$ 的叉乘矩阵啦~
Viewing transformation
2D 和 3D transformation 都是基础变换,接下来我们研究游戏里的画面是如何渲染到屏幕上的。
如下图所示,我们有一个摄像机、两个方块,那么我们是怎么计算出摄像机拍摄的画面的呢(参考右下角)?
我们按照下面的流程进行操作:
Camera transformation
首先,我们变换空间让摄像机位于坐标原点,且面向 $z$ 轴负方向,头顶朝 $y$ 轴正方向。对上图来说,就是把 $w$ 变换为 $z$ 轴,把 $v$ 变换为 $y$ 轴。
对应的矩阵是
这里的小技巧是,旋转矩阵的逆是其转置,所以我们先算出 $xyz$ 轴变换到 $uvw$ 轴的旋转矩阵,再对其转置,就得到了把 $uvw$ 变换到 $xyz$ 的矩阵。
Projection transformation
然后,我们把相机拍摄的区域变换到 $[-1,1]^3$ 中,这是一个规范化,为未来把区域放到屏幕上做准备。在此之前,我们要先确定相机能够拍摄的区域的范围。这里涉及到的变量主要有 fov、aspect ratio、near、far.
下图能清晰地解释 fov 和 aspect ratio。fov 即 field of view,表示用角度衡量的可见范围;aspect ratio 则是显示区域的宽高比。
near 和 far 则定义了剔除边界,我们只渲染满足 $z \in [\text{near}, \text{far}]$ 的东西。原点、近平面和原平面共同划分出了一块有限的空间,这就是摄像机拍摄的区域(视锥),我们会把他变换到 $[-1,1]^3$ 中。
在变换时,我们希望满足以下两点:
- near 和 far 平面上的点的 $z$ 值不变
- 近大远小,且缩放比例符合相似三角形的规律
结合齐次坐标,我们就能得到以下矩阵:
第一个等号右边的式子中,右边的矩阵把视锥压缩为一个长方体,左边的矩阵把这个长方体变换到 $[-1,1]^3$.
我们可以根据 $\text{near},\text{fov},\text{aspectRatio
}$ 求出 $l,t,r,b$.
也就是说,我们可以把投影矩阵写为:
Viewport transformation
最后,我们会把 $[-1,1]^3$ 的内容的宽高映射为屏幕大小。在这个变换中 $z$ 坐标不变,因此变换矩阵为:
总结
总而言之,我们的变换矩阵为
其中