三角形解剖
四段动画,拆的是 draw(3) 这一行背后发生的事:顶点函数跑了几次、坐标被怎么换、
哪些设置会让三角形消失,以及光栅化如何确定覆盖区域。顶点、坐标与粗网格扫描是 JavaScript 示意动画;剔除实验使用真实 WebGPU 渲染。
① draw(3):顶点函数跑三次
@vertex fn vs(@builtin(vertex_index) i : u32)
-> @builtin(position) vec4f {
let p = array<vec2f, 3>(
vec2f( 0.0, 0.5),
vec2f(-0.5, -0.5),
vec2f( 0.5, -0.5));
return vec4f(p[i], 0.0, 1.0);
}
| vertex_index | 返回的 vec4f |
|---|
同一个函数被调用三次,唯一的区别是 vertex_index。
这里逐次点亮是为了讲解,不代表 GPU 逐次执行;三个调用没有先后依赖。
② 同一个点,两套坐标:Y 朝上还是朝下
规范里的视口变换(画布按 280×280 算):
framebufferCoords(n) = (0.5 × (n.x + 1) × width, 0.5 × (−n.y + 1) × height)
| 顶点 | NDC (x, y) | 帧缓冲 (x, y) |
|---|
两张图里三角形的位置一模一样,变的只是编号方式:NDC 原点在正中、Y 朝上、范围 −1~1;
帧缓冲原点在左上、Y 朝下、单位是像素。公式里那个 −n.y 就是翻转。
③ 顺序写反了,三角形会不会消失
实测:等 WebGPU 初始化……
左边是按规范的面积公式算出来的判定,右边是同样配置下真跑一遍的结果, 还顺带把画出来的像素数数了一遍(渲染到一张 64×64 的离屏纹理,拷回内存数非透明像素)。 两边对不上,就是我的理解错了。
④ 光栅化示意:三角形覆盖哪些格子
@fragment fn fs() -> @location(0) vec4f {
return vec4f(1.0, 0.45, 0.2, 1.0);
}
这里用 JavaScript 检查哪些格子的中心落在三角形内。 计数器:0 个覆盖格子(28×28 粗网格)。这不是 GPU 片段调用次数的实测,也不能按画布尺寸直接推算调用次数。
这里的片段函数每次返回相同的颜色,所以是纯色。换成按 @builtin(position) 计算颜色,就能得到位置渐变;下一篇再看顶点颜色的插值。