简述
光栅化是将 3D 空间三角形投影至 2D 屏幕空间的过程。
基本流程
一个基本的光栅化器可按以下方式工作:
- 使用相机矩阵将三角形的顶点从世界空间(坐标系)变换到相机空间(坐标系)
- 使用视口变换矩阵将三角形的顶点从相机空间变换到NDC空间,即将 $x$、$y$、$z$ 分量映射到 $[-1, 1]$,其中 $z$ 又基于近裁剪平面和远裁剪平面进行映射。在这一步可以检查面法线是否和视线方向相同,方向不同则丢弃此片段(背面剪裁)
- 进行透视除法,将 $x$、$y$ 分量除以 $z$,将顶点变换到屏幕空间,在这一步可以检查顶点的缠绕顺序,不满足所需的顺序则丢弃此片段。
- 迭代三角形在屏幕空间中的可见区域的最小矩形包围区域(包围框),测试每个像素的中心点是否在三角形上,如果在,则计算并设置颜色值。这一步还可以通过插值计算片段的 z 深度值并检查是否小于之前绘制的点,如果不是可以丢弃此片段(深度测试)
Edge函数
此函数只是将两个向量叉乘,笛卡尔坐标向量叉积定义为 $a \times b = \lvert{a} \rvert \lvert{b} \rvert \sin{\theta}$,其中 $\theta$ 是向量间的夹角,由于向量叉乘不满足交换律且结果是有符号,可用于判断一点在向量的左侧或右侧(从向量指向的方向观察),可用于在二维中判断一点是在三角形上还是在三角形外。同时向量叉乘的结果还是向量构成的平行四边形的有符号面积。
重心坐标
重心坐标 $(\lambda_0,\lambda_1,\lambda_2)$ 是三个数组成的元组,可用于表示构成三角形的 $V_0$、$V_1$、$V_2$ 对于坐标系中一点 $P$ 的权重,$P$ 是三点的加权求和 $\lambda_0 \times V_0+\lambda_1 \times V_1+\lambda_2 \times V_2$。对于在三角形上的点,有 $\lambda_0 + \lambda_1 + \lambda_2 = 1$ 且 $\lambda_0 \geq 0, \lambda_1 \geq 0, \lambda_2 \geq 0$
可用于在 2D 屏幕空间中对视口空间中的顶点及其属性进行插值,原始顶点的 z 坐标的倒数可以进行线性插值。
摄像机空间的三角形 $V_0V_1V_2$ 和其上一点 $P$ 投影到屏幕空间 $V_0'V_1'V_2'$ 和 $P'$,$P'$ 关于三角形 $V_0'V_1'V_2'$ 的重心坐标为 $(\lambda_0,\lambda_1,\lambda_2)$,则有:
同时顶点属性 $C$ 也可以如此插值:
$$C_p = Z_p \times \left(\frac{\lambda_0 \times C_0}{Z_0} + \frac{\lambda_1 \times C_1}{Z_1} + \frac{\lambda_2 \times C_2}{Z_2} \right)$$三角形顶点 $V_i$ 关于三角形上点 $P$ 的权重 $B_i$ 是 $P$ 点与 $V_i$ 所在角对边构成的子三角形的有符号面积与大三角形面积之比。
左上规则
是一种着色规则,用于解决渲染透明片段时,重复渲染共用边造成错误的叠加,其中:
- 顶边缘是完全水平的边,构成其的顶点位于第三个顶点之上。从技术上讲,这意味着向量 V[(X+1)%3] - V[X] 的 y 坐标等于 0,并且其 x 坐标为正(大于 0)。
- 左边缘本质上是上升的边缘。鉴于在我们的上下文中顶点是按顺时针顺序定义的,如果构成一条边的向量 V[(X+1)%3] - V[X](其中 X 可以是 0、1、2)的y值为正,则该边被视为上升边缘。
执行着色时,仅着色处于三角形内部(不在边上)或在顶边或左边的点。
Z 缓冲
Z 缓冲区(深度缓冲区)是一个二维的浮点型数组,大小与画布大小相同,它是解决三角形重叠问题的方法之一,在绘制任意三角形的片段(像素点)之前:
- 首先计算该像素点的原始 z 坐标或深度。
- 将当前三角形的深度与该像素对于的深度缓冲区中的值进行比较。
- 如果存储在深度缓冲区中的值大于三角形该点的深度,则新点比深度缓冲区中该像素位置处存储的点更靠近观察者或相机。然后,深度缓冲区中存储的值将替换为新的深度,并且帧缓冲区将更新为当前的三角形颜色。另一方面,如果深度缓冲区中存储的值小于当前深度样本,则可以丢弃该像素。
在完成所有三角形的绘制后,深度缓冲区储存了场景可见区域到相机距离的图像。
抗锯齿
锯齿是在三角形的边缘处或纹理中出现的锯齿状边缘,解决方案称为抗锯齿(AA)。一种基于采样的抗锯齿方法是对同一像素进行多次不同位置的采样,像素通常被划分为 $N \times N$ 的网格,其中 $N$ 通常是 2 的幂(2、4、8 等),采样每个像素的”子像素“并计算平均值。
透视投影矩阵
透视投影矩阵变换摄像机空间中的坐标,将处于视锥体内处于近裁剪平面和远裁剪平面之间的 $x$、$y$、$z$ 坐标映射到 $[-1,1]$。设视锥体垂直视场的角度为 $Fov$,水平直视场角度与垂直视场角度比值为为 $a$,近裁剪平面距离为 $Z_n$,远裁剪平面距离为 $Z_f$,则透视投影矩阵为:
$$\begin{bmatrix} \frac{1}{a \times \tan{(Fov \div 2)}} & 0 & 0 & 0 \\ 3 & \frac{1}{\tan{(Fov \div 2)}} & 0 & 0 \\ 0 & 0 & \frac{ Z_n + Z_f}{Z_n - Z_f } & \frac{2 \times Z_n \times Z_f}{Z_n - Z_f} \\ 0 & 0 & -1 & 0 \end{bmatrix}$$投影 x、y:
$$\begin{align*} \frac{1}{a \times \tan{(Fov \div 2)}} \\\ \frac{1}{\tan{(Fov \div 2)}} \end{align*}$$由于 $x$、$y$ 坐标在屏幕空间中被映射到 $[-1,1]$,而将视场为 90° 的对称视口内的坐标归一化总是落在此范围内,乘以此值相当于将当前视口内顶点的 $x$、$y$ 变换到视场角为 90° 的视口内。
投影 z:
将视锥体裁剪平面内 z 坐标映射到 $[-1, 1]$ 有如下推导:设矩阵第 3 行 3 列和 3 行 4列 分别为 $a$ 和 $b$,求其值。
由于变换后需要保留原始 z 坐标取负作为 w, 因此第四行第三列为 -1