阶段 3 · 3D基础18 分钟
实例化:一次 draw 绘制大量对象
instance_index 与 stepMode: instance
把每个实例的位置、比例和颜色放进实例缓冲区,一次 draw 绘制数百个几何体。
LEARNING GOALS
先明确本课目标
1
配置 instance vertex buffer
2
使用 instance_index
3
减少大量重复 draw 调用
MENTAL MODEL · 再建立心智模型
顶点数据描述“一个网格长什么样”,实例数据描述“每个副本放在哪里、长多大、什么颜色”。
MINIMAL EXAMPLE
怎样用一次 Draw 绘制很多相同网格?
Instancing 复用同一套顶点数据,并为每个实例提供不同变换或材质。@builtin(instance_index) 表示当前实例编号。
wgsl@vertex
fn vs(
@builtin(vertex_index) vertex: u32,
@builtin(instance_index) instance: u32,
) -> @builtin(position) vec4f {
let offset = instanceOffsets[instance];
return vec4f(corners[vertex] + offset, 0.0, 1.0);
}
// JavaScript: pass.draw(6, 100);- vertex 变化最快 每个实例都执行完整的 vertexCount 次顶点调用。
- instance 选择数据 用 instance_index 从数组、Vertex Buffer 或 Storage Buffer 读取每实例参数。
- 减少 CPU 调用 一条 draw 命令可提交几十到成千上万个实例。
draw(6, 100) 产生 600 次顶点调用,但 CPU 只发出一次 Draw。
OPTIONAL · 按需查阅完整术语表与概念边界遇到陌生术语时再展开,不打断主线实验。
展开⌄
着色器内建值instance_index当前实例序号,用于实例化绘制或从数组/存储缓冲区读取每实例数据。几何数据arrayStride相邻两个顶点或实例记录在缓冲区中的字节间隔。几何数据VertexStepMode决定顶点缓冲区记录按 vertex 还是 instance 前进。绘制Instancing一次 draw 复用同一网格绘制多个实例,通过 instance 数据或 instance_index 区分。几何数据stepMode: instance让 Vertex Buffer 每绘制一个实例才前进一条记录,而不是每个顶点前进。几何数据Instance Buffer保存每实例变换、颜色等属性的 Vertex Buffer,通常配合 stepMode: instance 使用。绘制Draw CallCPU 记录的一次 draw/drawIndexed 命令;实例化可让一次调用提交许多相同网格。
LIVE EXPERIMENT · 先获得反馈
边改边运行
浏览器加载后会激活代码编辑器、独立运行环境与实时输出。
本课挑战
用 storage buffer 取代 instance vertex buffer。
回到原理,解释刚才发生了什么
先用结果建立反馈,再按运行流程、核心原理和知识关系逐层深入。
CORE IDEA
核心讲解
实例步进
stepMode: vertex 每个顶点前进一次,stepMode: instance 每个实例前进一次。二者可同时绑定。
降低 CPU 开销
大量独立 draw 会增加命令编码与状态设置成本。实例化把重复网格合并成一次调用。
OPTIONAL · 迁移时查阅WebGPU 与 WebGL2 对照主线实验完成后,再用完整映射处理跨平台或跨 API 迁移。
展开⌄
实例化的收益与数据组织相同,差别在 divisor 状态和 stepMode 描述。
WebGL
drawArraysInstanced/drawElementsInstanced 配合 vertexAttribDivisor 提供实例属性。
WebGPU
draw 的 instanceCount 配合 stepMode: instance 或 instance_index。
WebGPU stepMode 属于 Pipeline;不要期待像 WebGL 那样在 draw 前临时修改 divisor。