图形学篇 — 变换

Posted by Xun on Monday, September 26, 2022

变换,指将数据通过一定的规则进行转换,通常可以用矩阵来进行表示。

简介

  • 在计算机图形学中,变换的使用非常常见,如:平移、缩放、旋转等。变换主要分为
    • 线性变换
      • 可以保留矢量加和标量乘的变换,即
        • f(x) + f(y) = f(x + y)
        • kf(x) = f(kx)
      • 缩放(scale)、旋转(rotation)、错切(shear)、镜像(mirroring)、正交投影(orthography projection)等
    • 仿射变换
      • 线性变换和平移变换的合并
  • 对于常见的变换,其变换矩阵分别为
    • 平移 Math_Transform_1.png
    • 缩放 Math_Transform_2.png
    • 旋转(绕x、y、z轴) Math_Transform_3.png Math_Transform_4.png Math_Transform_5.png
  • 对于复合变换,需要按照先缩放,再旋转,最后平移的顺序,才能保证最后得到正确的效果。
  • 在 Unity 中,坐标系是按照 y-x-z 的逐级组合的,如果绕世界坐标系下的固定坐标轴旋转,需要按照 zxy 的顺序。如果绕自身坐标系旋转,由于旋转时自身坐标系也会发生改变,根据坐标系的次序,需要按照 yxz 的顺序进行旋转,即 Math_Transform_6.png
  • 在图形学计算中,从CPU传入的顶点坐标,需要从模型空间,变换到世界空间,再变换到视图空间,再变换到裁剪空间,最后变换到屏幕空间。从模型空间变换到裁剪空间,就是常说的 MVP 变换。

模型变换

  • 模型变换,即将坐标从模型空间变换到世界空间。在 Unity 中,如果一个 GameObject 没有父节点,那么其坐标即为世界空间下的坐标。如果存在父节点,则其自身坐标即为模型空间下的坐标,需要进行变换。变换为复合变换,将所有父节点的信息累计起来,进行平移、缩放和旋转。假设父节点的坐标为(x,y,z),角度为(θ,0, 0),则最终模型变换的变换矩阵即为 Math_Transform_7.png

视图变换

  • 相机决定了渲染使用的视角,在视图空间下,相机的坐标为原点坐标,x轴正向为右方,y轴正向为上方,z轴正向为相机后方。尽管 Unity 在模型空间和世界空间下使用的都是左手坐标系,但在观察空间下, Unity 和 OpenGL 一样,使用右手坐标系,因此,相机的正前方为 -z 。
  • 为了将物体变换到视图空间下,需要对应的变换矩阵。若将相机变换到世界坐标下的原点,并旋转到与坐标轴重合,再将相机的 z 方向取反,此时对应物体经过同样的变换后,在世界空间下的信息即为在视图空间下的信息。假设相机在世界空间下的坐标为(x,y,z),角度为(θ,0, 0),则视图变换矩阵为 Math_Transform_8.png

投影变换

  • 相机最终渲染的范围为其视锥体范围,在视锥体内的正常渲染,视锥体外的则剔除,与视锥体相交的则会被裁剪,只保留视锥体内的部分。对于正交投影,视锥体是一个长方体,计算对象是否在其范围相对比较简单,而透视投影是一个锥体,计算难度则相对较大。另外,由于每个相机都有各自的参数,所以各自的视锥体都不一样,因此计算起来也更加复杂。为了能统一到一个通用、简单的结构下进行计算,则需要进行投影变换。
  • 视锥体的一些表示
    • l :近裁剪平面的左边
    • r :近裁剪平面的右边
    • t :近裁剪平面的上边
    • b :近裁剪平面的下边
    • n :近裁剪平面的距离(正)
    • f :远裁剪平面的距离(正)

正交投影

  • 正交模式下,视锥体是一个长方体,要将长方体视锥体变换到以 (0, 0) 为中心, [-1, 1] 范围的正方体内,因此需要执行两个步骤
    • 将视锥体中心移动到坐标原点
    • 将视锥体进行缩放,形成 [-1, 1] 的正方体
  • 所以正交投影矩阵为 Math_Transform_9.png Math_Transform_10.png

透视投影

  • 透视模式下,视锥体是一个截掉顶部的锥体,和正交模式不一样,所以需要进行的操作为
    • 将视锥体变换为长方体
    • 按照正交投影进行投影变换
  • 为了将视锥体变换为长方体,首先需要将视锥体的 x、y 坐标投影到近裁剪平面对应的坐标值。 Transform_1.png
  • 可以看到,视锥体上的点的关系为 Math_Transform_11.png Math_Transform_12.png
  • 因此,变换过程为 Math_Transform_13.png
  • 可以推出变换矩阵 Math_Transform_14.png
  • 由于远近裁剪平面经过变换后,还是保持不变,对于近裁剪平面上的点,z = z' = -n ,则有 Math_Transform_15.png
  • 因此可以得到,变换矩阵为 Math_Transform_16.png
  • 同样,对于远裁剪平面上的点,z = z' = -f ,则有 Math_Transform_17.png
  • 可以得到 Math_Transform_18.png Math_Transform_19.png
  • 因此变换矩阵为 Math_Transform_20.png
  • 则最终透视投影的变换矩阵为 Math_Transform_21.png Math_Transform_22.png

齐次除法(透视除法)

  • 经过投影变换后,得到的视锥体,需要投影到屏幕空间中。然而可以发现,正交投影和透视投影得到的视锥体并不是统一的,所以需要统一转换到 NDC(Normalized Device Coordinates)中,即将 x、y、z、w 都除以 w 分量。
  • 正交投影变换为 Math_Transform_23.png 由于 w 分量为 1,因此齐次除法后保持不变。
  • 透视投影变换为 Math_Transform_24.png 由于 w 分量为 -z,所以 x、y、z 都要除以 -z,从而将视锥体转换到 [-1, 1] 范围里。

总结

  • 计算机图形学中,变换的应用非常多,渲染时基本上离不开坐标变换,理解各个过程的变换矩阵,也有助于理解整个渲染的过程。