本文以工程视角梳理光栅化的核心概念与实现要点:光栅化可以统一理解为对二维指示函数的采样。在此基础上,分别说明像素中心采样、点在三角形内判定(边函数/叉积同侧)、边界像素归属规则(Top-Left Rule)以及常见的性能优化手段(Bounding Box 与增量计算)。
1. 核心概念:光栅化在做什么
光栅化的本质是:把连续的几何图形(通常是三角形)转换为离散像素表示。
从计算角度可以统一为:
- 定义一个二维指示函数(Indicator Function)
- 对该函数在像素采样点上进行采样
- 将采样结果写入帧缓冲(颜色、深度等)
直观表述:
光栅化 = 对二维指示函数进行采样

2. 指示函数(Indicator Function)
在二维屏幕空间中,定义:
inside(tri, x, y)
含义:
- 点 ((x, y)) 在三角形内 → 返回 1
- 点 ((x, y)) 在三角形外 → 返回 0
数学表达:
f(x,y)={1,(x,y)∈triangle0,otherwise
f(x, y)=
\\begin{cases}
1, & (x,y)\\in triangle \\\\
0, & \\text{otherwise}
\\end{cases}
f(x,y)={1,0,(x,y)∈triangleotherwise
在渲染实现里,这个 0/1 结果会决定“该像素是否被该三角形覆盖(covered)”。

3. 光栅化基本流程(最小版本)
最直接的实现是遍历像素并判断覆盖关系:
for (int x = 0; x < xmax; ++x)
for (int y = 0; y < ymax; ++y)
image[x][y] = inside(tri, x + 0.5, y + 0.5);
关键点:
- 遍历像素网格(离散)
- 对每个像素使用采样点(通常是像素中心)
- 根据 inside 结果写入像素(覆盖)
4. 为什么使用 (x + 0.5, y + 0.5):像素中心采样
像素在几何意义上是一个区域(小方块),而不是数学意义上的点。常见约定:
- ((x, y)):像素左下角
- ((x+0.5, y+0.5)):像素中心(采样点)
GPU 默认的规则通常采用中心采样(Center Sampling)。工程上这样做的好处是:
- 采样位置明确、可复现
- 与后续抗锯齿(如 MSAA 的多采样点)逻辑一致
5. 点在三角形内的判定:边函数(Edge Function)/叉积同侧
光栅化最核心的几何判断是:一个采样点是否被三角形覆盖。常用方法是“对三条边做同侧测试”。
三角形顶点:
P0,P1,P2
P_0, P_1, P_2
P0,P1,P2
对每条边定义边向量,并对点 (P) 计算叉积符号(二维里可以视为 z 分量):
C0=(P1−P0)×(P−P0)
C_0 = (P_1-P_0)\\times(P-P_0)
C0=(P1−P0)×(P−P0)
C1=(P2−P1)×(P−P1)
C_1 = (P_2-P_1)\\times(P-P_1)
C1=(P2−P1)×(P−P1)
C2=(P0−P2)×(P−P2)
C_2 = (P_0-P_2)\\times(P-P_2)
C2=(P0−P2)×(P−P2)
判定规则:
- 若 (C_0, C_1, C_2) 全部同号 → 点在三角形内部(或边上,取决于边界规则)
- 否则 → 点在三角形外部
几何意义:
点必须位于三条边的同一侧。
工程实现中常将这一类判定写成“边函数(edge function)”,以便做增量更新优化。
6. 边界问题(Edge Cases)与 Top-Left Rule
问题:如果采样点刚好落在三角形边上,属于哪个三角形?
在网格化渲染中,两个相邻三角形共享边,若规则不一致会导致:
- 重叠:两个三角形都认为该像素属于自己
- 裂缝:两个三角形都不认为该像素属于自己
常见工业做法:Top-Left Rule:
- 上边、左边:判为“内侧”(包含)
- 下边、右边:判为“外侧”(不包含)
目标:
- 让每个像素只归属一个三角形
- 避免裂缝与重叠
7. 性能问题与优化路径
7.1 暴力遍历的问题
若对整个屏幕做 inside 测试,会产生大量无效计算,因为三角形通常只覆盖局部区域。
7.2 Bounding Box(包围盒)优化

先计算三角形在屏幕空间的最小包围矩形:
minX,maxX,minY,maxY
minX, maxX, minY, maxY
minX,maxX,minY,maxY
只遍历该区域:
for x in [minX, maxX]
for y in [minY, maxY]
inside(...)
收益:大幅减少无效像素测试,是最基础且高收益的优化。
7.3 增量计算(Incremental Computation)
边函数在屏幕空间是线性函数,相邻像素的结果只差一个常量偏移,因此可以递推:
- ((x,y)\\rightarrow(x+1,y)) 可通过“上一个值 + 常量”得到
- 避免每个像素重新计算叉积/边函数
收益:减少重复计算,属于硬件光栅化的常见优化思路。
8. 完整光栅化流程(概念版)
9. 统一认知模型
光栅化可以统一理解为:
几何→函数→采样→离散图像
\\text{几何}\\rightarrow \\text{函数}\\rightarrow \\text{采样}\\rightarrow \\text{离散图像}
几何→函数→采样→离散图像
GPU 的工作可以抽象为:
for each pixel:
if inside(triangle):
shade() // 进入插值/深度测试/片元着色等
10. 后续知识点(建议的衔接顺序)
光栅化只是开始,通常下一步会接:
- 重心坐标(Barycentric Coordinates)与属性插值(颜色/UV/法线)
- 深度测试(Z-buffer)
- 抗锯齿(MSAA/SSAA 与采样点)
- 纹理采样与过滤(Bilinear/Trilinear/MipMap)
总结一句话
光栅化 = 判断像素是否被三角形覆盖(inside)+ 在离散网格上对覆盖结果采样与填充,并在工程上通过边界规则与遍历/递推优化保证正确性与性能。

