WebGPU instancing
WebGL에서 instanced rectangle renderer를 살펴봤습니다. WebGPU에서도 같은 아이디어를 씁니다. unit rectangle geometry는 공유하고, node마다 instance data를 보냅니다.
instance stepMode를 쓰는 코드
WebGPU에서는 vertex buffer layout에서 stepMode: "instance"를 지정해 instance data를 분리합니다.
const pipeline = device.createRenderPipeline({
layout: "auto",
vertex: {
module: shader,
entryPoint: "vs_main",
buffers: [
{
arrayStride: 2 * 4,
stepMode: "vertex",
attributes: [
{ shaderLocation: 0, offset: 0, format: "float32x2" }
]
},
{
arrayStride: 8 * 4,
stepMode: "instance",
attributes: [
{ shaderLocation: 1, offset: 0, format: "float32x4" },
{ shaderLocation: 2, offset: 4 * 4, format: "float32x4" }
]
}
]
},
fragment,
primitive: { topology: "triangle-list" }
});
draw 시점에는 unit quad buffer와 instance buffer를 각각 slot에 연결합니다.
pass.setPipeline(pipeline);
pass.setVertexBuffer(0, unitQuadBuffer);
pass.setVertexBuffer(1, instanceBuffer);
pass.draw(6, instanceCount);
WGSL에서는 @location(1)의 rect와 @location(2)의 color가 instance마다 바뀝니다.
@vertex
fn vs_main(
@location(0) unit: vec2f,
@location(1) rect: vec4f,
@location(2) color: vec4f
) -> VertexOut {
let world = rect.xy + unit * rect.zw;
// world -> clip matrix 적용 후 반환
}
vertex buffer를 역할별로 나눈다
하나는 vertex마다 달라지는 unit rectangle position입니다. 다른 하나는 instance마다 달라지는 node data입니다.
slot 0: vertex position
slot 1: instance transform / size / color
WebGPU pipeline의 vertex buffer layout에서 stepMode: "instance"를 지정합니다.
instance data는 scene node cache다
rectangle node 하나를 instance row 하나로 만들 수 있습니다.
node id
transform
size
fill color
이 데이터는 renderer cache입니다. scene model이 바뀌면 다시 만들거나 일부 갱신합니다.
draw call은 instance count를 가진다
unit rectangle vertex 6개와 instance N개를 조합해서 그립니다.
pass.draw(6, instanceCount);
이것은 많은 rectangle을 적은 draw command로 그리는 핵심 패턴입니다.
오늘의 핵심
WebGPU instancing은 Figma-like editor의 rectangle/image node에 잘 맞습니다.
shared quad
many instance rows
one pipeline
one draw
WebGL에서 배운 구조를 WebGPU vertex buffer layout으로 옮긴 것입니다.