Skip to content

光栅化(三角形的离散化)

图形管线在经过顶点着色器与投影变换后,几何体(如三角形)处于连续的数学空间中。屏幕或帧缓冲则是由离散像素构成的二维网格。光栅化 (Rasterization) 的核心目标,是将连续的几何形状转换为离散的屏幕采样点,为后续的计算生成候选状态——即片元 (Fragment)

将连续三角形映射到离散网格的基础方法是覆盖测试 (Coverage Test)。硬件光栅化器通过检查像素中心点是否落在三角形内部来判断覆盖状态。

判定点是否在三角形内部的标准数学方法是使用向量叉乘构造边缘方程。假设三角形三个顶点按逆时针顺序排列为 A(x0,y0)A(x_0, y_0)B(x1,y1)B(x_1, y_1)C(x2,y2)C(x_2, y_2),对于平面上任意一点 P(x,y)P(x, y),可以构造由边向量与点 PP 构成的二维叉乘:

EAB(x,y)=(x1x0)(yy0)(y1y0)(xx0)E_{AB}(x, y) = (x_1 - x_0)(y - y_0) - (y_1 - y_0)(x - x_0)

如果点 PP 位于三角形内部,则它必须同时满足位于三条有向边的左侧,即 EAB0E_{AB} \ge 0EBC0E_{BC} \ge 0ECA0E_{CA} \ge 0。这在本质上应用了第一章中向量叉乘在二维空间中判定方向的几何意义。

在真实的 GPU 硅片设计中,光栅化过程集成了大量依赖数学特性的性能优化机制:

用于判定边缘方程的向量叉乘,同时表征了三角形的有向面积 (Signed Area)。若顶点在屏幕空间中呈顺时针排列(即整个三角形的二维叉乘结果符号为负),图形管线会直接判定该三角形背向摄像机,并将其完全剔除,阻断后续的像素覆盖测试。

为了避免遍历全屏像素,光栅化器首先计算三角形的轴对齐包围盒 (AABB),提取坐标极值以缩小测试范围。 现代 GPU 架构进一步引入了分块光栅化 (Tile-based Rasterization)。屏幕被划分为固定尺寸的宏块(如 8×88 \times 8 像素)。硬件通过测试三角形与整个块的相交关系,快速批量剔除不相交的网格区域。

3. 边缘方程的增量计算法 (Incremental Evaluation)

Section titled “3. 边缘方程的增量计算法 (Incremental Evaluation)”

边缘方程 E(x,y)E(x, y) 是关于 xxyy 的线性函数。在逐像素测试时,GPU 不会对每个像素重复执行两乘两减的完整代数公式。 根据线性函数的导数特性,当光栅化器在屏幕网格的水平方向步进一个像素(即 xx+1x \to x+1)时,方程的值仅需累加一个固定的斜率常数 Δy=y0y1\Delta y = y_0 - y_1;在垂直方向步进时,只需累加 Δx=x1x0\Delta x = x_1 - x_0。这种以单次加法替代复数次乘法运算的底层设计,是硬件光栅化具备极高吞吐量的数学基础。

拖动三角形的顶点 A, B, C,观察光栅化器如何计算边界包围盒 (AABB),并通过判定边缘方程的符号 (E ≥ 0) 来决定哪些像素的中心点被覆盖,从而生成片元。
  1. 获取屏幕坐标:假设三角形三个顶点位于 A(1,1)A(1, 1)B(5,2)B(5, 2)C(3,6)C(3, 6)
  2. 计算包围盒:边界为 X[1,5]X \in [1, 5]Y[1,6]Y \in [1, 6]
  3. 遍历中心点:取包围盒内某像素中心点 P(3.5,3.5)P(3.5, 3.5) 进行测试。
  4. 执行边缘方程
    • ABAB 向量为 (4,1)(4, 1)APAP 向量为 (2.5,2.5)(2.5, 2.5)。叉乘 EAB=4×2.51×2.5=7.50E_{AB} = 4 \times 2.5 - 1 \times 2.5 = 7.5 \ge 0
    • BCBC 向量为 (2,4)(-2, 4)BPBP 向量为 (1.5,1.5)(-1.5, 1.5)。叉乘 EBC=2×1.54×(1.5)=30E_{BC} = -2 \times 1.5 - 4 \times (-1.5) = 3 \ge 0
    • CACA 向量为 (2,5)(-2, -5)CPCP 向量为 (0.5,2.5)(0.5, -2.5)。叉乘 ECA=2×(2.5)(5)×0.5=7.50E_{CA} = -2 \times (-2.5) - (-5) \times 0.5 = 7.5 \ge 0
  5. 生成片元:三个叉乘结果均大于等于 00,判定点 P(3.5,3.5)P(3.5, 3.5) 位于三角形内部,在此位置生成片元。

当两个三角形共享一条边时,边上的采样点会产生归属歧义。为避免同一采样点产生重复片元(冗余计算)或不产生片元(导致几何体之间出现缝隙),图形 API 统一定义了严格的光栅化边界规则。

以 Direct3D 和 OpenGL 中采用的“左上边缘规则” (Top-Left Rule) 为例:只有当边位于三角形的左侧(非水平边,且在数学上向右递增)或上侧(水平边)时,恰好落在该数学边上的像素中心才被判定属于该三角形。

三角形仅在三个顶点处定义了位置、颜色、法线与纹理坐标等属性。为了向三角形内部生成的片元传递这些数据,需要执行空间插值。

重心坐标 (Barycentric Coordinates) 是解决三角形内部插值的标准数学工具。对于三角形内部的任意点 PP,可以由三个顶点 AABBCC 线性组合表示:

P=αA+βB+γCP = \alpha A + \beta B + \gamma C

其中,权重满足 α+β+γ=1\alpha + \beta + \gamma = 1。 在几何上,这些权重可通过子三角形面积与总面积的比值计算:

  • α=SPBC/SABC\alpha = S_{\triangle PBC} / S_{\triangle ABC}
  • β=SPCA/SABC\beta = S_{\triangle PCA} / S_{\triangle ABC}
  • γ=SPAB/SABC\gamma = S_{\triangle PAB} / S_{\triangle ABC}

这套权重可等效应用于任意顶点属性的插值计算:

AttributeP=αAttributeA+βAttributeB+γAttributeCAttribute_P = \alpha Attribute_A + \beta Attribute_B + \gamma Attribute_C
α (A: 红) = 0.33 β (B: 绿) = 0.33 γ (C: 蓝) = 0.33
插值颜色:
拖动点 P,观察重心坐标 α, β, γ 的权重变化,以及顶点颜色是如何通过这些权重在三角形内部进行线性插值混合的。

假设三角形顶点 AA 为纯红 (1,0,0)(1, 0, 0)BB 为纯绿 (0,1,0)(0, 1, 0)CC 为纯蓝 (0,0,1)(0, 0, 1)。 若某片元 PP 的位置计算得出的重心坐标为 α=0.2\alpha = 0.2β=0.3\beta = 0.3γ=0.5\gamma = 0.5。 则该片元的插值颜色为:

ColorP=0.2×(1,0,0)+0.3×(0,1,0)+0.5×(0,0,1)=(0.2,0.3,0.5)Color_P = 0.2 \times (1, 0, 0) + 0.3 \times (0, 1, 0) + 0.5 \times (0, 0, 1) = (0.2, 0.3, 0.5)

片元着色器接收到的即为经过此离散化插值后生成的平滑过渡数据。

在三维空间经透视投影至屏幕空间后,屏幕上的线性距离并不等同于三维空间中的实际线性距离。

直接在屏幕的二维空间中对深度 ZZ 坐标或纹理坐标 U,VU, V 进行线性插值,会导致错误的视觉映射。在具有透视收缩(Perspective Foreshortening)效果的视图中,远处物体的像素密度应大于近处。若在屏幕空间实施线性混合,物体表面的纹理会出现明显的仿射扭曲失真。

为了解决该误差,图形管线硬件会执行透视校正插值 (Perspective-Correct Interpolation)

数学推导表明,虽然顶点属性 II 在屏幕空间中不呈线性分布,但属性与透视除数 WW 的比值(即 I/WI/W),以及 1/W1/W 本身,在屏幕空间中保持严格的线性变化。因此,现代 GPU 执行透视校正的实际计算步骤如下:

  1. 在屏幕空间中,使用重心坐标 α,β,γ\alpha, \beta, \gamma 对顶点的 1/W1/W 进行线性插值,求得当前片元的深度倒数 1/WP1/W_P
  2. 使用相同的重心坐标对 I/WI/W(如 U/WU/WV/WV/W)进行线性插值,求得当前片元透视投影后的属性项 IP/WPI_P/W_P
  3. 将计算得到的 IP/WPI_P/W_P 除以 1/WP1/W_P,恢复出符合三维透视关系的原始属性 IPI_P

通过上述数学步骤,硬件光栅化器在进行离散采样的同时,确保了三维透视信息的物理准确性。