想象一下粉刷匠老王接到一个活儿:在一面贴着整齐方格瓷砖的墙上,刷出一个巨大的三角形图案。瓷砖就是屏幕上的像素,三角形就是 3D 模型投射到屏幕上的形状。老王得先想清楚三件事:第一,哪些瓷砖该刷、哪些不该刷?第二,三角形边缘只盖住一半的瓷砖,是刷还是不刷?第三,如果客户要求渐变漆——离红角近的偏红、离蓝角近的偏蓝——每块瓷砖的颜色怎么调?这面墙上有上万个三角形要画,怎么才能刷得又快又不漏? 这套问题,正是图形渲染管线里「三角形设置与遍历」要解决的核心。三角形设置,相当于老王提前在墙上用粉笔画出三角形的三条边,并圈出一个工作范围;遍历,则是老王一格格扫过瓷砖,判断每块要不要刷漆、刷什么颜色;再配合重心坐标调色、边缘抗锯齿和平行施工,最终把一个个三角形变成屏幕上细腻逼真的画面。
理解光栅化的底层原理,是进入渲染引擎、实时图形学与三维 AI 感知方向的必备基础。它能帮你读懂 GPU 在“画”什么、为什么快、瓶颈在哪,无论是做游戏引擎、工业可视化还是神经渲染,都能少走很多弯路。
可视化演示
展示图形渲染管线光栅化核心流程:三角形边方程计算、包围盒像素遍历与重心坐标插值,步进式探索光栅化各阶段。
本节配有交互动效(进入视口后自动加载,约 3KB)。
边方程:三角形设置 三顶点确定三条边的隐式方程 E(x,y) = ax + by + c 符号判定像素在三角形内外
渲染管线定位
老王的装修队分工非常明确:量尺寸的师傅先上门,用测量仪把客厅的角角落落都定位好,在图纸上标出三个角的位置;老王是刷漆工,专门负责上墙;等漆刷完,贴壁纸的师傅再接手,把好看的纹理纸糊上去。这样一条流水线,每道工序各司其职,谁都不必操心别人的活儿。
这条流水线在图形学里叫渲染管线,里面的角色分工与装修队如出一辙。顶点处理就像量尺寸的师傅:它把 3D 模型的每个顶点做坐标变换、光照计算,最后投影到屏幕坐标,输出一个个二维三角形。老王对应的就是光栅化阶段——把二维三角形变成屏幕上覆盖的像素。而光栅化结束后的片元着色,则是贴壁纸的师傅:拿着老王标注好的像素,逐一算出最终颜色。
光栅化之所以是管线中央的瓶颈工序,是因为它的工作量与屏幕像素直接挂钩:一个三角形在屏幕上可能只占巴掌大,也可能覆盖半面墙,需要处理的像素数量从几十到几百万不等。三角形设置与遍历,正是光栅化的两半:设置是提前把三角形在屏幕上的“施工图纸”准备好,遍历是按照图纸一格格落实。到了现代 GPU 里,老王一个人变成了一整支施工队——成百上千个着色器核心同时开刷,靠的正是这套图纸足够清晰、足够规则。
三角形设置
老王接到图纸后,第一件事不是拿刷子,而是拿起粉笔,在墙上沿着三角形的三条边描出笔直的粉笔线。这三条线就是他的“边界线”:瓷砖中心落在线内侧才值得刷漆。接着他又从兜里掏出一个硬纸框,套在三角形外面——纸框正好是能框住三角形的最小矩形,老王把精力全集中在这个框里,墙的其他角落一概不看。
在渲染管线里,这三条粉笔线就是边方程。屏幕上的三角形由三个顶点定义,任意一条边都可以写成一个直线方程:把该边的两个端点代入一个特定算式,就能得到该直线的数学表达;再把任意一个像素坐标代入,得到的结果就能告诉我们这个像素在边的哪一侧。三角形有三条边,于是有三个边方程,它们共同构成内外判定规则。而那根纸框,就是包围盒——取三个顶点横纵坐标的最小值和最大值,围出一个轴对齐矩形。因为三角形一般只占据屏幕一小块,包围盒能把遍历缩小到最小必要范围。
边方程的具体计算并不神秘,它就是二维叉积的展开:
老王把三条粉笔线画完,又把纸框套好,施工范围一目了然。到了这一步,三角形的“施工图”已经齐活:边方程管边界判定,包围盒管工作范围,接下来就能一格格检查瓷砖了。
- 构造边向量先取顶点 A 到顶点 B 的有向边向量,它指明了这条粉笔线的方向和倾斜程度
- 代入待测点把像素中心点 p 与顶点 A 的连线和边向量做二维叉积,叉积展开后就是上面的公式
- 符号定区域叉积结果的正负表示 p 落在有向边的哪一侧,0 表示恰好在线上
像素遍历
画好线的老王有个好习惯:不跳着刷,也不乱点。他从纸框的左上角开始,像扫地一样,先沿着第一行从左往右一路看过去,看完一行再回到第二行开头,一行一行地扫到右下角。这样扫过每一块瓷砖,他都会停下来蹲下看一眼,瓷砖中心在粉笔线内侧就点一刷子,在外侧就跳过。
这个“扫地式”的检查过程就是像素遍历。计算机并不知道三角形内部具体覆盖了哪些像素,只能笨办法:把包围盒里每个像素都问一遍“我是不是在三角形里”。具体做法是,对每个像素取其中心点坐标,代入三个边方程,如果结果都为非负(约定三角形内部在三条边的同一侧),就判定该像素被三角形覆盖。这个判定过程称为覆盖测试。
覆盖测试的条件写成数学式是:
其中 \(w_0, w_1, w_2\) 分别是三个边函数代入像素中心后的值。
老王扫完整面墙后,三角形内部的瓷砖都被他点了漆。不过细心的他会发现一个问题:有些瓷砖真的很想被刷到——可它们的中心点恰好落在粉笔线外一点点。为了照顾这些“边缘户”,老王会在后续环节想些辙,那是抗锯齿的事;眼下遍历已经把“该扫的地方”全部扫过了,不重不漏。
- 取像素中心把像素看作一个小方格,取其中心作为测试点,避免方格四角跨越多块区域造成歧义
- 三个边函数分别代入依次把 p 代入 AB、BC、CA 三条有向边的方程
- 联立判断只有当三个值都大于等于零时,p 才被判定在三角形内部
重心坐标
客户这次要求很高,要刷渐变漆:离红色角近的瓷砖偏红,离蓝色角近的偏蓝,离黄色角近的偏黄。老王掏出一个小天平,先把三角形大区域分成三块小三角形——从这块瓷砖的位置向三个顶点各拉一条线,就得到三块小三角形,它们的面积之比,恰好决定了三桶漆各倒多少。这个面积比例,就是图形学里的重心坐标。
重心坐标是光栅化里最重要的调色工具。像素 p 在三角形内部时,三个边函数值两两组合可以算出三块小三角形的面积,将它们归一化就得到三个权重 \(\lambda_0, \lambda_1, \lambda_2\)。这三个权重满足和为 1,且分别对应三个顶点的“影响力”:权重越大,像素越靠近那个顶点。任何顶点属性——颜色、法线、纹理坐标,都能用这三个权重做线性组合,插值出当前像素处应有的值。
重心坐标的计算公式如下:
不过,老王很快发现一个陷阱:墙是平面的,但客户的图案是 3D 投影到墙上的,直接用屏幕上的平面比例调色,会让远处的地砖纹理“漂移”。要修正这个问题,需要透视校正:在插值前,先把每个顶点的属性值除以该顶点在裁剪空间的 w 分量(它近似等于深度),插值完成后再除以权重的 w 倒数之和。这样,3D 空间里原本均匀的纹理,投到屏幕上才依然均匀。
有了老王的这杆“天平”,每一块瓷砖的色号都精确无比。这个看似简单的面积比例,撑起了整个片元着色阶段对颜色、深度、法线等无数属性的插值需求。
- 顶点属性的深度压缩每个顶点的属性值先除以它的裁剪坐标 w,让离相机远的数据在混合时权重变小
- 用重心坐标做线性混合对压缩后的数值做普通线性插值
- 恢复正确的插值结果再除以同样插值得到的 \(1/w\),完成深度修正
边缘抗锯齿
刷完大半面墙后,老王退后几步端详,发现三角形边缘的瓷砖出现了明显的“狗啃”——有的瓷砖只盖住一小半也被刷成了全漆,远看就是参差不齐的阶梯。他挠挠头:这个问题不在粉笔线,而在瓷砖本身的判定规则。每一块瓷砖要么全刷要么不刷,覆盖率只有 0% 和 100% 两个档位,边缘自然毛糙。
这就是锯齿的本质:像素是离散的,三角形边缘与像素网格相交处,覆盖率无法用连续值表达,只好近似成“非黑即白”。要磨平它,老王想了个聪明的办法:把每块瓷砖想象成有四个采样点(四个角),数一数有几个采样点落在粉笔线内,再按比例决定刷多浓——四个点都在内的刷全漆,三个点在内刷七成浓,两个点在内刷半浓。边缘的瓷砖从“全有或全无”变成了“浓淡渐变”,远看就是平滑的直线。
这个办法就是超采样抗锯齿(MSAA),覆盖率公式写出来是:
老王的“半浓油漆”策略相当划算:整块在内部的瓷砖仍只算一次颜色,只有边缘瓷砖才需要多算几次覆盖率。他满意地再看看墙,三角形的边缘已经光滑得像用尺子比着画出来的。这个磨平锯齿的功夫,GPU 硬件里早已内置了 4x、8x 甚至 16x 的采样模式,让现代游戏画面的边缘又细又顺。
\text{coverage} = \frac{1}{N} \sum_{i=1}^{N} I(s_i), \quadI(s_i) = \begin{cases} 1 & s_i \in \triangle \\ 0 & s_i \notin \triangle \end{cases}- 在像素内布置采样点每个像素内部放 N 个采样位置,常见 4x MSAA 就放 4 个
- 逐一测试归属每个采样点用边函数判断是否位于三角形内,在内记 1,在外记 0
- 求覆盖率把 N 个采样点的归属结果取平均,得到 0 到 1 之间的覆盖率
并行加速
一人一刷,把这面墙刷完得干到天黑。老王灵机一动:不如叫上几个徒弟合伙干。他把墙用粉线切成若干等大的方块,小张负责左上角那一块,小李负责右上角,小赵负责下半部分——大家各刷各的格子,互不干扰,一上午就能收工。这就是分块并行的思路:把大任务切成小块,分给不同的工人同时处理。
GPU 里的光栅化沿用了同样的智慧。现代 GPU 有上千个计算核心,屏幕画面被切成许多渲染分块(tile),每个分块交给一个或多个核心独立完成光栅化与着色。分块带来的额外好处是数据局部性好——同一块屏幕区域的数据能待在高速缓存里,不必频繁回显存。一个分块处理完,整块像素一起写回,带宽开销也小。
分块方案的计算很简单:
其中 \(W\) 是屏幕宽,\(H\) 是屏幕高,\(B\) 是分块边长(如 8、16、32 像素)。
除了分块,光栅化还有两个天然的并行层次。一是像素级并行:三角形内部像素各自独立计算,没有先后依赖,一个三角形里几百个像素可以同时做覆盖测试;二是三角形级并行:场景里的三角形彼此独立,GPU 会把一批三角形一次性分给众多核心同时处理。老王的小团队就这样把三个层次的并行叠加起来——每人刷一块,每块里好几个动作同时做,效率提升几十倍不止。
- 确定分块尺寸每个分块是边长 B 像素的正方形区域
- 计算行列块数屏幕宽除以 B 后向上取整,得到每行分块数;高同理
- 总块数行列块数相乘,即任务总数
优化技巧
老王是个有心人,干活干多了,总结出三招省力秘诀。第一招:一行瓷砖扫到一半,发现已经出了粉笔线范围,后面几块不用再蹲下看,直接跳到下一行;这就是遍历中的早退测试。第二招:同一行的相邻瓷砖,蹲下判断时发现每次的计算结果都有规律——往右挪一块瓷砖,边函数的数值只需要在上一个基础上加一个固定数,根本不必重新算一遍公式;这就是增量计算。第三招:他把天平、漆桶全放在手边,不走冤枉路;在计算机里,这叫数据局部性——让访问过的数据待在缓存里,下次取用就快。
增量计算的数学直觉很优雅。边函数的表达式里,横坐标每增加 1,结果的变化量恰好是边的纵向分量;纵坐标每增加 1,结果的变化量是边的横向分量的相反数。于是计算量从 O(1) 还是 O(1),但省掉了整条公式里多次乘法和减法,也让流水线更容易做硬件优化。公式如下:
早退测试在大型三角形上效果显著:如果某个分块整体都在三角形内部,就省去逐像素的边方程测试,直接整块填充;如果整体都在外部,也可以整块跳过。老王把这套“省力三招”教给了徒弟们,刷墙队伍从此又快又稳,这正是光栅化工程里性能优化的核心思路——能少算的绝不多算,能递推的绝不重算,能缓存的一定缓存。
- 向右走一步横坐标增加 1 时,边函数增加一个与边向量纵向分量相等的常数
- 向下跨一行纵坐标增加 1 时,边函数减少一个与边向量横向分量相等的常数
- 两个常数提前算好这两个增量在三角形设置阶段就固定下来,遍历时只需做加法
AI 应用场景
游戏引擎实时渲染
阶段:模型训练与推理前的图形数据采样
解决的问题:游戏引擎需要每秒钟把上百万个三角形光栅化成 1080p 甚至 4K 画面的像素。传统手工绘制无法实时响应玩家操作,而 GPU 利用三角形设置与遍历的并行流水线,在 16 毫秒内完成整帧渲染。
具体案例:在 Unity 或 Unreal 引擎中,角色模型由数万个三角形组成,摄像机视角一变,光栅化阶段立刻重新计算每个三角形的覆盖像素,再交给片元着色器输出颜色。优化三角形布局、减少过度绘制,都要基于对遍历和覆盖测试的理解。
自动驾驶点云可视化与 BEV 投影
阶段:感知数据的预处理与可视化
解决的问题:LiDAR 点云是无序的 3D 点集,直接送入神经网络前往往要栅格化成规则的鸟瞰图(BEV)。传统做法是手工体素化,速度慢且信息有损;利用三角网格化与光栅化投影,可以快速把点云路面重建为三角形网格,再用三角形设置与遍历把网格投到 2D 栅格,供检测模型使用。
具体案例:自动驾驶测试中,工程师将路测点云重建为地面三角形网格,光栅化后叠加到前视摄像头画面上,生成带深度标注的训练数据,供 BEV 感知模型学习。
神经渲染的合成数据生成
阶段:训练数据的生成与增强
解决的问题:NeRF、3D Gaussian Splatting 等神经渲染模型需要大量多视角图像,但真实采集成本高。传统方式手动摆放并渲染 3D 场景,依赖 CPU 渲染速度慢;利用 GPU 光栅化流水线,三角形设置与遍历能以极快速度批量生成不同视角、不同光照的合成图像。
具体案例:某机器人团队在仿真环境中摆放数千个虚拟物体,用光栅化管线从 200 个随机视角渲染出图像,自动标注出每个像素的物体 ID 和深度,作为视觉模型的训练集,一天即可生成过去一个月才能攒下的数据量。
Python 演示
class SoftwareRasterizer: def __init__(self, width, height): self.width = width self.height = height self.frame = [[0.0] * width for _ in range(height)] def edge_func(self, a, b, p): return (p[0] - a[0]) * (b[1] - a[1]) - (p[1] - a[1]) * (b[0] - a[0]) def bounding_box(self, v0, v1, v2): xs = [v0[0], v1[0], v2[0]] ys = [v0[1], v1[1], v2[1]] min_x = max(0, int(min(xs))) max_x = min(self.width - 1, int(max(xs))) min_y = max(0, int(min(ys))) max_y = min(self.height - 1, int(max(ys))) return min_x, min_y, max_x, max_y def rasterize(self, v0, v1, v2): area = self.edge_func(v0, v1, v2) if abs(area) < 1e-9: return min_x, min_y, max_x, max_y = self.bounding_box(v0, v1, v2) for py in range(min_y, max_y + 1): for px in range(min_x, max_x + 1): p = (px + 0.5, py + 0.5) w0 = self.edge_func(v1, v2, p) w1 = self.edge_func(v2, v0, p) w2 = self.edge_func(v0, v1, p) if w0 >= 0 and w1 >= 0 and w2 >= 0: lambda0 = w0 / area lambda1 = w1 / area lambda2 = w2 / area self.frame[py][px] = lambda0 * 0.8 + lambda1 * 0.3 + lambda2 * 0.1 def to_ascii(self): chars = " .:-=+*#%@" rows = [] for py in range(self.height): row = [] for px in range(self.width): v = self.frame[py][px] if v <= 0: row.append(".") else: idx = min(len(chars) - 1, int(v * (len(chars) - 1))) row.append(chars[idx]) rows.append("".join(row)) return "\n".join(rows) def main(): rast = SoftwareRasterizer(56, 24) v0 = (4.0, 22.0) v1 = (50.0, 1.0) v2 = (52.0, 23.0) rast.rasterize(v0, v1, v2) print(rast.to_ascii()) if __name__ == "__main__": main()
def edge_func(self, a, b, p)计算边函数,返回 p 在有向边 a→b 的哪一侧,正值表示左侧。def bounding_box(self, v0, v1, v2)取三个顶点在 x、y 方向的最小/最大值,生成遍历用的包围盒。if w0 >= 0 and w1 >= 0 and w2 >= 0:三个边函数同时非负,判定像素中心在三角形内部。lambda0 = w0 / area用边函数比值直接得到重心坐标的第一个分量,用于后续颜色插值。self.frame[py][px] = lambda0 * 0.8 + lambda1 * 0.3 + lambda2 * 0.1按重心坐标混合三个顶点的亮度值,形成渐变填充。to_ascii()把浮点亮度映射到字符密度,输出可视化结果,亮度高用@,亮度低用空格。
常见误区
误区我总觉得只要像素方块跟三角形有一点点重叠,这个像素就应该被填色,毕竟“眼见为实”,看起来碰到了嘛。
正解标准光栅化的判定依据是像素中心点(或采样点)是否落在三角形内部,而不是像素方块是否与三角形相交。这是因为 GPU 需要一种确定性的规则避免邻接三角形同时点亮同一个像素;如果按方块相交来算,三角形会“膨胀”一圈,而且边缘的归属会摇摆不定。
为何常见:生活中判断“这块砖要不要刷漆”看的是砖面是否被颜料碰到,而 GPU 是从采样点出发的数学模型,两者天然不同,初学者最容易踩这个坑。
误区重心坐标的数值大,说明这个点离对应顶点更远,就像距离一样,重心坐标衡量的是几何远近。
正解重心坐标是三个子三角形面积的比例,是归一化到和为 1 的仿射量。它确实与“靠近哪个顶点”正相关,但并不是欧氏距离。两个点在三角形内可能重心坐标相同,而实际到顶点的直线距离完全不同;重心坐标的价值在于它随位置线性变化,方便插值。
为何常见:从“离顶点近颜色占比高”这个直觉出发,容易把它理解成距离的度量,忽略了它其实是面积比的数学本质。
误区抗锯齿嘛,就是让画面更清晰,把渲染分辨率提高一些再缩放下来,边缘自然就平滑了。
正解MSAA(多重采样抗锯齿)并不是简单提升分辨率或全屏模糊。它的做法是在像素内部放置多个采样点,仅对处于三角形边缘的像素计算覆盖率并混合颜色;像素内部完全不额外做片元着色。这比全屏超采样便宜得多,也不会让画面变糊。
为何常见:从“锯齿是像素不够密”出发,自然想到提高分辨率这条最直接的路,而没意识到问题出在边缘覆盖率无法连续表达,MSAA 恰恰是在这个局部位置上做文章。
误区遍历到某一行,发现有一个像素不在三角形里,就提前跳到下一行,那这一行后面本来该刷的像素岂不就漏了?
正解光栅化中的提前终止并不是“遇到一个不覆盖就放弃整行”,而是利用三角形在行方向的跨度信息,只遍历当前扫描线与三角形相交的有效区间。配合增量边方程,可以精准知道一行的起点和终点,跳出区间外的无效测试,绝不会漏掉内部像素。
为何常见:字面意思上“提前终止”容易被误解为无限期提前收工,实际它是建立在几何单调性之上的区间裁剪,属于遍历的数学性质而非粗暴剪枝。
面试题
Q1. 光栅化阶段最初的输入是什么?
- A.屏幕上的四边形网格
- B.变换后的二维三角形← 正确答案
- C.顶点着色后的像素颜色
- D.处理完毕的纹理贴图列表
答案:B。光栅化的输入是顶点处理完成后、投影到屏幕坐标的二维三角形。四边形不是基本图元,像素颜色是光栅化之后片元着色才有的产出,纹理贴图也只是辅助属性,选 B 最准确。
Q2. 边函数 E_AB(p) > 0 表示点 p 位于边 AB 的哪一侧?
- A.位于三角形的外部区域
- B.位于有向边 AB 的右侧
- C.位于有向边 AB 的左侧← 正确答案
- D.恰好落在边 AB 的中点上
答案:C。边函数本质是向量 AB 与向量 Ap 的二维叉积,正负对应左右侧。约定正值表示点在有向边的左侧,负值在右侧,零在线上。这点决定了三角形覆盖测试的方向约定,也解释了为什么换顶点顺序会得到相反符号。
Q3. 标准光栅化中判断一个像素是否被三角形覆盖的依据是?
- A.像素四个角都落在三角形内
- B.像素中心点位于三角形内部← 正确答案
- C.像素与三角形有面积重叠
- D.三角形边长超过像素边长
答案:B。标准做法是取像素中心点作为采样点,用边方程判定其是否位于三角形内部。四角全在过于严格,面积重叠会过度扩张三角形,边长对比与覆盖无关。中心点规则是硬件实现里最常用的确定性测试。
Q4. 关于重心坐标,下列说法正确的是?
- A.可用来插值颜色和深度等顶点属性← 正确答案
- B.可用来求三角形外接圆的半径尺寸
- C.三个分量非负且和为 1 时可以判定点在三角形内← 正确答案
- D.数值大小与摄像机远近有直接正比关系
答案:AC。重心坐标是面积比的归一化,天然用来做属性插值,A 正确;同时它也是内外判定的一种形式,三个分量都非负等价于点在三角形内部,C 正确。重心坐标与外接圆、相机深度没有直接关系,B、D 错误。
Q5. 4x MSAA 在每个像素内部做了什么事?
- A.把整个画面连续渲染四遍再合并
- B.在边缘像素内放 4 个采样点求覆盖率← 正确答案
- C.把画面放大 4 倍再进行全屏锐化
- D.计算四张不同分辨率的缩略图
答案:B。4x MSAA 在每个像素内布置 4 个采样点,在三角形边缘处统计落在内部的采样点比例得到覆盖率,并将覆盖率用于颜色混合。只有边缘像素承担额外开销,内部像素依然只做一次片元着色。
Q6. 包围盒在光栅化遍历中的主要作用是?
- A.防止三角形顶点越出视口边界
- B.把遍历范围缩小到三角形外接矩形← 正确答案
- C.预先存储三角形所有的像素颜色
- D.提升顶点坐标变换的精度等级
答案:B。包围盒是三角形顶点横纵坐标的最小外接轴对齐矩形。光栅化只在这个矩形内扫描,避免了全屏幕逐像素测试的无谓开销,是遍历加速的第一层保障。
Q7. 下列哪些手段可以加速像素遍历阶段?
- A.用包围盒限制扫描范围← 正确答案
- B.用增量递推代替逐像素重算边方程← 正确答案
- C.把屏幕划分为分块并行处理← 正确答案
- D.给每个顶点重新分配索引编号
答案:ABC。包围盒缩小扫描范围、增量递推减少单个像素计算量、分块并行提升多核心利用率,都是经典加速手段。顶点索引重排主要影响顶点缓存命中率,与像素遍历阶段无直接关系。
Q8. 透视校正插值的根本目的是?
- A.让远处的物体在屏幕上变得更小
- B.修正深度缓冲区的比较精度
- C.让纹理坐标在透视投影下保持正确← 正确答案
- D.减少三角形边缘出现的锯齿现象
答案:C。屏幕空间线性插值在透视投影下并不等于三维空间线性变化,直接插值会导致纹理扭曲。透视校正把顶点属性先除以 w 再插值,最后除以插值后的 1/w,从而把屏幕像素正确映射回三维空间的原始位置。
Q9. 关于边函数的增量计算,下列说法正确的是?
- A.同一行内相邻像素的边函数差值恒定← 正确答案
- B.每个像素的边函数必须从头完整重算
- C.跨行移动也会产生一个固定差值← 正确答案
- D.增量只对三角形的顶点有效果
答案:AC。边函数 E(x,y) 对 x 和 y 的偏导都是常数,所以同行相邻像素只差一个固定增量,跨行同理。正因如此,硬件遍历器只需维护几个整数累加器,不必每像素重算公式,A、C 正确而 B 错误;增量法与顶点本身无关,D 错误。
Q10. 覆盖测试中采用“三个边函数都大于等于 0”而非“大于 0”的原因是什么?
- A.保证点在三角形内部时数值更大
- B.避免共享边上的像素被重复点亮← 正确答案
- C.让三角形的颜色插值更均匀
- D.提高包围盒命中率
答案:B。零值代表点恰好在边上。若边界像素被两个相邻三角形同时判定为内部,就会出现重复绘制与闪烁。通过约定零值归一侧三角形,再配合“左上填充规则”,可以确保共享边上的像素只属于一个三角形,从而避免重复光栅化。