GAMES101第四课笔记 - MVP 变换

这是本系列第三篇笔记,对应了第四课的内容:课程录像课件。这一课主要讲解了三维变换(被我整合到了上一篇笔记中)与 MVP (Model, View, Projection) 变换。

MVP (Model View Projection) 变换

类比为拍照的过程:

  1. 摆好人 Model Transformation
  2. 找好角度 View Transformation
  3. 茄子~ 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}\)

    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 轴会发生变化?

    发表回复

    您的电子邮箱地址不会被公开。 必填项已用 * 标注

    此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据