about 图形学中的投影变换,也就是从视图(摄像头)坐标系投影坐标系的过程。

属于图形学系列文章

经过前面的视图变换后,虚拟摄像头已经对准了原点,我们现在要做的就是把3D的坐标映射到2D的平面上,这个过程叫投影变换。它有两种类别:透视投影(Perspective projection)、平行投影(Parallel projection)

Perspective Projection

以上图中的左图为参考,我们需要定义有关 Image plane 的一些变量:left <= x <= right | bottom <= y <= top | z = -near | z = -far,每个变量以首字母命名,分别为 l、r、b、t、n、f

The origin(摄像头的位置) and the image plane(观察对象) defines a pyramid 金字塔

The truncated version of this pyramid (between z = -near and z = -far) is called the frustum 视锥体

可以看出,这里 x_p 和 y_p 和 -z 是成反比的,在 homogeneous coordinates 下,我们这样设定坐标:

$$ \left(\begin{array}{c}{x^{\prime}} \\ {y^{\prime}} \\ {z^{\prime}} \\ {-z}\end{array}\right) \sim\left(\begin{array}{c}{x^{\prime} /-z} \\ {y^{\prime} /-z} \\ {z^{\prime} /-z} \\ {1}\end{array}\right) $$

如何求解投影矩阵?

同样的,我们能得出来:

$$ y_{c}=\frac{2 n}{t-b} y+\frac{t+b}{t-b} z $$

对于z轴,我们想要进行两个转换: (i) z = -n to z = -1 (ii) z = -f to z = 1

最终我们计算能得到整个投影矩阵,非常非常重要!

$$ M_{p}=\left(\begin{array}{cccc}{\frac{2 n}{r-l}} & {0} & {\frac{r+l}{r-l}} & {0} \\ {0} & {\frac{2 n}{t-b}} & {\frac{t+b}{t-b}} & {0} \\ {0} & {0} & {-\frac{f+n}{f-n}} & {-\frac{2 f n}{f-n}} \\ {0} & {0} & {-1} & {0}\end{array}\right) $$

特别的,当 frustum 是对称的情况时 (i.e., r + l = 0, t + b = 0,Let r - l = w(idth) and t - b = h(eight))

$$ M_{p}=\left(\begin{array}{cccc}{\frac{2 n}{w}} & {0} & {0} & {0} \\ {0} & {\frac{2 n}{h}} & {0} & {0} \\ {0} & {0} & {-\frac{f+n}{f-n}} & {-\frac{2 f n}{f-n}} \\ {0} & {0} & {-1} & {0}\end{array}\right) $$

This transformation is NOT affine -> does not preserve parallel lines,有近大远小的特点

Z-Fighting z轴变换后的结果是非线性的 z_c / (-z) (齐次坐标归一化) 和 1/z 成正比关系。This can cause floating-point precision issues when the range of [-n, -f] gets large 也就是越远越看不太清楚

Perpendicular Parallel Projection

Clip Space -> Frame Buffer

很可能存在三维空间中多个点映射到同一个二维坐标上,此时我们需要引入 frame buffer,去存储z值,也就是每个片段(fragment i.e., point on a triangle)的深度值。

  • If fragment depth < frame buffer pixel depth: Overwrite

  • If fragment depth > frame buffer pixel depth: Skip