这是本系列第三篇笔记,对应了第四课的内容:课程录像、课件。这一课主要讲解了三维变换(被我整合到了上一篇笔记中)与 MVP (Model, View, Projection) 变换。
MVP (Model View Projection) 变换
类比为拍照的过程:
- 摆好人 Model Transformation
- 找好角度 View Transformation
- 茄子~ Projection Transformation
Model 模型变换
主要是将模型坐标借助上一课所讲的三维变换将其变换到世界坐标。
View 视图变换
- 定义相机:
- 相机的位置 \(\vec e\)
- 看的方向 \(\hat g\)
- 相机的向上方向 \(\hat t\)
- 相机的标准位置:
- 放在原点
- 朝向 \(-\vec z\)
- 向上为 y 轴正方向
- 如何得到 \(M_{view} = R_{view}\,T_{view}\)
- 平移 \(\vec e\) 至原点
- \(T_{view}=\begin{bmatrix}1&0&0&-x_e\\0&1&0&-y_e\\0&0&1&-z_e\\0&0&0&1\end{bmatrix}\)
- 记变换前的 \(\hat g\times\hat t\) 为 \(\hat p\),并:将 \(\hat g\)、\(\hat t\)、\(\hat p\) 分别旋转到 \(-z\)、\(y\)、\(x\)
- 两个注意的地方:
- 一、课件原文用的 rotate 可能有点歧义,我认为这个过程应该更像是「切变变换」,与「旋转变换」没有联系
- 二、课件原文用的「旋转 \(\hat g\times\hat t\) 至 \(x\)」也有点歧义,应该是「旋转」之前的 \(\hat g\times\hat t\)
- 要 \(\hat g\to-z\) 很难,但是反过来很容易:\(-z\to\hat g\) 即 \(z\to-\hat g\)
- \(z\to-\hat g\) 记为 \(\textbf R^{-1}_{view} = \begin{bmatrix}x_{\hat g\times\hat t}&x_{\hat t}&x_{-\hat g}&0\\y_{\hat g\times\hat t}&y_{\hat t}&y_{-\hat g}&0\\z_{\hat g\times\hat t}&z_{\hat t}&z_{-\hat g}&0\\0&0&0&1\end{bmatrix}\)
- 由于旋转矩阵是正交矩阵,所以有性质 \(\textbf R_{view}=(\textbf R^{-1}_{view})^T\)
- 因此有 \(\textbf R_{view} = \begin{bmatrix}x_{\hat g\times\hat t}&y_{\hat g\times\hat t}&z_{\hat g\times\hat t}&0\\x_{\hat t}&y_{\hat t}&z_{\hat t}&0\\x_{-\hat g}&y_{-\hat g}&z_{-\hat g}&0\\0&0&0&1\end{bmatrix}\)
- 两个注意的地方:
- 平移 \(\vec e\) 至原点
Projection 投影变换
Orthographic Projection 正交投影
- 先定义一个「可视范围」:
左 l 右 r 上 t 下 b 近 n 远 f
- 目标:将其映射到一个规范立方体 canonical cube:\([-1, 1]^3\)
- 如何做变换 \(M_{ortho} = S_{ortho}\,T_{ortho}\)
- 平移 \(T_{ortho} = \begin{bmatrix}1&0&0&-\frac{r+l}2\\0&1&0&-\frac{t+b}2\\0&0&1&-\frac{n+f}2\\0&0&0&1\end{bmatrix}\)
- 缩放 \(S_{ortho} = \begin{bmatrix}\frac2{r-l}&0&0&0\\0&\frac2{t-b}&0&0\\0&0&\frac2{\textbf{n-f}}&0\\0&0&0&1\end{bmatrix}\)
Perspective Projection 透视投影
- 目标:将视锥体「挤压」为一个长方体,再用正交变换转换到规范立方体 \([-1, 1]^3\)
- 如何做变换 \(M_{persp} = M_{ortho}\,M_{persp\to ortho}\)
- 先做「挤压」,根据相似三角形有 \(y'=\frac nzy\)、\(x'=\frac nzx\),所以点 \(\begin{pmatrix}x\\y\\z\\1\end{pmatrix}\) 可以变换为 \(\begin{pmatrix}\frac nzx\\\frac nzy\\\textit{unknown}\\1\end{pmatrix}\)
- 根据齐次坐标的特性,可以将该点写为 \(\begin{pmatrix}nx\\ny\\\textit{unknown}\\z\end{pmatrix}\)
- 建立方程,可解出部分矩阵 \(M_{persp\to ortho} = \begin{bmatrix}n&0&0&0\\0&n&0&0\\\textit ?&\textit ?&\textit ?&\textit ?\\0&0&1&0\end{bmatrix}\)
- 又由两个特殊约定:
- 近面上的任意点 z 轴不变
- 远面上的任意点 z 轴不变
- 可解出完全的投影矩阵 \(M_{persp\to ortho} = \begin{bmatrix}n&0&0&0\\0&n&0&0\\0&0&n+f&-nf\\0&0&1&0\end{bmatrix}\)
- 一般情况下,n、f、fovY、aspect ratio 已知,l、r、t、b 不会直接给出
- 怎么求?
- \(\tan\frac{fovY}2 = \frac t{|n|}\)
- \(\textit{aspect ratio} = \frac rt\)
- 怎么求?
Viewport Transformation 视口变换
- 屏幕的定义
- 光栅成像
- 由像素组成
- 分辨率
- \(M_{viewport} = \begin{bmatrix}\frac{\textit{width}}2&0&0&\frac{\textit{width}}2\\0&\frac{\textit{height}}2&0&\frac{\textit{width}}2\\0&0&1&0\\0&0&0&1\end{bmatrix}\)
一些仍然没有解决的疑问
- 在解 \(M_{persp\to ortho}\) 矩阵的第三行时,为什么直接就能确定前两个数是 0?
- 课程论坛能搜到一篇解答,但是仍然没有解答我的疑问。
- 实际上,做完透视投影之后,z 轴的值只要仍然保持旧有的大小关系,就不会对深度检测造成影响。那么在 \(M_{persp\to ortho}\) 的过程中直接将 z 轴保持原样,而非「正确的非线性映射方法」,这个做法可不可行呢?
- 关于课后提问,「在近面及远面之间的点,在挤压后的 z 轴是离哪一面更近了还是保持不变?」,为什么 z 轴会发生变化?