GPU 干两件事:① 把顶点流处理成裁剪空间顶点;② 据此画像素。 上一课把 ① 走完了,本课整段都在 ② 里面。
本节点在骨架 ② 的第 1 环——顶点已经是合法的屏幕坐标了,可屏幕上一个像素都还没点亮。
从「三个点」到「一片像素」这一步叫光栅化。它只回答一个问题:哪些像素被这个三角形盖住了? 判定方法是边函数——对每个像素中心,看它落在三条边的哪一侧;三条边同侧,就算被盖住。 这一步同样是固定功能,也没有 shader。本段只增加一样东西:覆盖判定。
右列那片格子不是三角形本身,是「被三角形盖住的像素」。三角形是连续的,格子是离散的——这个落差就是锯齿的来源。
真实像素在屏幕上小到看不见,所以这里的格子是被放大过的像素。把格子调细,锯齿跟着变细——
这就是「分辨率越高越平滑」的全部内容。
一句必须说清的话:硬件光栅器内部到底怎么判覆盖,WebGPU 里看不到。
所以画面上的覆盖判定是页面按同一条边函数自己重算的,不是从 GPU 读回来的——这一点已用角标标出。
跑不起来先看设备要求:活例由真 GPU 出画面 —— 手机需 Android 12+ 且 Chrome 121+,或 iOS / iPadOS 26+;电脑需 Chrome / Edge 113+ 或 Safari 26+。Android 上取不到适配器多是设备不支持 Vulkan 1.1+,会自动改走兼容模式(需 Chrome 146+)。不满足时画面区会写出原因与自查步骤,同一页的示意图与数值表照常可读。
先只拖像素尺寸:格子变细,边缘变平滑,但三角形没动。再拖平移 / 旋转:被盖住的格子整片跟着走。 判定一直只有一条:三条边同侧。
| # | x | y |
|---|
| 边 | a | b |
|---|
| 项 | 值 | |
|---|---|---|
知道光栅化就是逐格做覆盖判定、判定靠边函数同号;也知道锯齿不是 bug,是像素的边界—— 想让它更细,只能提高分辨率。
本节点在骨架 ② 的第 2 环——像素已经被盖住了,但它们还都是同一个颜色。
上一段回答了「哪些像素被盖住」,可那一片像素还没拿到任何变化的信息。 顶点着色器只会跑 3 次,而像素有成千上万个——中间的差值是硬件插出来的: 按三个顶点各占多少重心权重,把它们的值混成每一个像素的值。 本段只增加一样东西:varying(顶点到片元的插值)。
顶点着色器只跑了 3 次,可整片像素的颜色各不相同:3 个值被摊成了成千上万个值。这就是 varying 的全部内容。
把鼠标移到三角形上:十字线那一点的三个重心权重与插值结果会实时出现在件三。
你可以拿 w0·c0 + w1·c1 + w2·c2 手算,再和画面上的颜色对。
切到「三顶点同值」:三个顶点给一样的值,插出来自然还是一样的值——一片纯色。 所以插值不会创造信息,它只做加权平均。
把鼠标在三角形里慢慢移动。注意看:越靠近某个顶点,那个顶点的值在结果里占比越大——件三的权重会告诉你「大多少」。
| # | x | y |
|---|
| # | r | g |
|---|
| 项 | 值 | |
|---|---|---|
w0·c0 + w1·c1 + w2·c2。
它与十字线所在像素的颜色应当一致——硬件做的就是这件事。
知道顶点着色器只跑 3 次而像素有成千上万;也知道中间的差值是硬件按重心权重插出来的—— 它只做加权平均,不创造信息。