US2S1L18——裁剪空间变换的意义

知识回顾

  • 齐次裁剪空间
    齐次裁剪空间是通过将摄像机的视锥体投影到一个规范化的立方体(长宽高都为2,位于原点)而转换来的。
    这个立方体就是齐次裁剪空间。是为了让我们可以更通用、便捷的来进行裁剪工作

  • 观察空间到裁剪空间变换要分情况考虑

    • 摄像机为正交投影时:

      1. 将视锥体中心位移到观察空间原点中心
      2. 将长方体视锥体的xyz坐标范围映射到(-1,1)长宽高为2的正方体中

      正交投影变换矩阵为:

      (1Aspect×Size00001Size00002FarNearNear+FarFarNear0001)\begin{pmatrix} \frac{1}{Aspect \times Size} & 0 & 0 & 0 \\ 0 & \frac{1}{Size} & 0 & 0 \\ 0 & 0 & -\frac{2}{Far - Near} & -\frac{Near+Far}{Far - Near} \\ 0 & 0 & 0 & 1 \\ \end{pmatrix}

    • 摄像机为透视投影时:

      1. 将透视视锥体变成一个长方体
      2. 将视锥体中心位移到观察空间原点中心
      3. 将长方体视锥体的xyz坐标范围映射到(-1,1)长宽高为2的正方体中

      透视投影变换矩阵为:

      (1Aspecttan(FOV2)00001tan(FOV2)0000Far+NearFarNear2FarNearFarNear0010)\begin{pmatrix} \frac{1}{Aspect \cdot \tan(\frac{FOV}{2})} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan(\frac{FOV}{2})} & 0 & 0 \\ 0 & 0 & -\frac{Far + Near}{Far - Near} & -\frac{2 Far\cdot Near}{Far - Near} \\ 0 & 0 & -1 & 0 \\ \end{pmatrix}

裁剪空间变换的意义

我们之所以要将观察空间中的顶点等信息变换到裁剪空间中主要意义,
其实就是为了让我们可以更通用、便捷的来进行裁剪工作。

因为如果直接使用视锥体定义的空间来进行裁剪,那不同的视锥体就需要不同的处理过程,
比如正交摄像机的 Size、Near、Far 等参数,透视摄像机中的 FOV、Near、Far 等参数
他们决定了视锥体的体积大小会各不相同,而且对于透视投影的视锥体来说,判断顶点是否在其范围内相对较麻烦。

因此前辈们就制定了裁剪空间这一规则,让我们可以更容易的完成裁剪工作,这也是该变换的意义所在

如何决定顶点是否被裁剪

对观察空间下的顶点进行裁剪空间变换后,得到的点(x,y,z,w)(x,y,z,w)

  • 正交摄像机的裁剪判断方式:

    {1x11y11z1(位于此范围内就是不需要裁剪的)\begin{cases} -1 \le x \le 1 \\ -1 \le y \le 1 \\ -1 \le z \le 1 \end{cases} (位于此范围内就是不需要裁剪的)

  • 透视摄像机的裁剪判断方式

    {wxwwywwzw(位于此范围内就是不需要裁剪的)\begin{cases} -w \le x \le w \\ -w \le y \le w \\ -w \le z \le w \end{cases} (位于此范围内就是不需要裁剪的)

首先我们还是之前用于举例的顶点来说明

模型空间下的顶点坐标为(0.63, 0.84, -0.04)
当模型进行2倍缩放,又进行(0, 45, 0)的旋转,然后再进行(5 ,0, 5)的平移后
该顶点的世界空间下的坐标为(5.834, 1.68, 4.052)

摄像机的轴向和坐标为

1
2
3
4
print(this.transform.right);        //x轴
print(this.transform.up); //y轴
print(-this.transform.forward); //z轴,注意,观察空间是右手坐标系,因此取后方
print(this.transform.position); //原点位置

image

转换到观察空间后的坐标为(4.562, 0.659, -7.722, 1)

假设屏幕宽高比为:image

如果是正交摄像机,参数为:image

将数据代入到正交投影变换矩阵内,得到:

(1Aspect×Size00001Size00002FarNearNear+FarFarNear0001)(4.5620.6597.7221)=(0.5132250.12580.4922841)\begin{pmatrix} \frac{1}{Aspect \times Size} & 0 & 0 & 0 \\ 0 & \frac{1}{Size} & 0 & 0 \\ 0 & 0 & -\frac{2}{Far - Near} & -\frac{Near+Far}{Far - Near} \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} 4.562 \\ 0.659 \\ -7.722 \\ 1 \\ \end{pmatrix} = \begin{pmatrix} 0.513225 \\ 0.1258 \\ 0.492284 \\ 1 \\ \end{pmatrix}

显然,这个点的 x,y,zx,y,z 都在(1,1)(-1,1)的范围内,故不需要裁剪

如果是正交摄像机,参数为:image

将数据代入到透视投影变换矩阵内,得到:

(1Aspecttan(FOV2)00001tan(FOV2)0000Far+NearFarNear2FarNearFarNear0010)(4.5620.6597.7221)=(4.4461.1767.21427.722)\begin{pmatrix} \frac{1}{Aspect \cdot \tan(\frac{FOV}{2})} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan(\frac{FOV}{2})} & 0 & 0 \\ 0 & 0 & -\frac{Far + Near}{Far - Near} & -\frac{2 Far\cdot Near}{Far - Near} \\ 0 & 0 & -1 & 0 \\ \end{pmatrix} \begin{pmatrix} 4.562 \\ 0.659 \\ -7.722 \\ 1 \\ \end{pmatrix} = \begin{pmatrix} 4.446 \\ 1.176 \\ 7.2142 \\ 7.722 \\ \end{pmatrix}

要注意,此时我们求出来的坐标其 ww' 不为1,我们必须要除以 ww' 标量使其为1,这样得出来的坐标才是三维空间下真正的坐标

(4.4461.1767.21427.722)÷7.722=(0.57570.1520.93421)\begin{pmatrix} 4.446 \\ 1.176 \\ 7.2142 \\ 7.722 \\ \end{pmatrix} {\div} 7.722 = \begin{pmatrix} 0.5757 \\ 0.152 \\ 0.9342 \\ 1 \\ \end{pmatrix}

显然,这个点的 x,y,zx,y,z 都在(1,1)(-1,1)的范围内,故不需要裁剪