Geometry and buffer layouts
Quick answer
This tutorial explains the three layers between typed arrays and the GPU: the array, the Buffer and the layout declaration. It shows createBuffer with explicit usage flags such as VERTEX, INDEX, UNIFORM, STORAGE, COPY_DST and COPY_SRC, then defines bufferLayout entries with name, stepMode and format. It describes interleaved records through byteStride and byteOffset, instance step modes, and Geometry versus GPUGeometry. Readers can feed vertices without silent attribute mismatches.
Key points
- Declare Buffer.VERTEX, INDEX and COPY_DST usage flags explicitly when needed.
- Match bufferLayout names to shader in variables and formats to component counts.
- Describe interleaved data with byteStride and a per-attribute byteOffset.
Example
const positions = device.createBuffer(new Float32Array([
-0.6, -0.45, 0,
0.6, -0.45, 0,
0.0, 0.55, 0
]));
const dynamic = device.createBuffer({
data: new Float32Array(3 * 2048),
usage: luma.Buffer.VERTEX | luma.Buffer.COPY_DST
});
const indices = device.createBuffer({
data: new Uint32Array([0, 1, 2]),
usage: luma.Buffer.INDEX,
indexType: 'uint32'
});
dynamic.write(newData); // 覆盖写入
console.log(dynamic.byteLength, dynamic.updateTimestamp);const model = new luma.Model(device, {
vs: vsSource,
fs: fsSource,
attributes: {
positions: device.createBuffer(new Float32Array([...])),
colors: device.createBuffer(new Float32Array([...]))
},
bufferLayout: [
{ name: 'positions', stepMode: 'vertex', format: 'float32x3' },
{ name: 'colors', stepMode: 'vertex', format: 'float32x3' }
],
vertexCount: 3,
topology: 'triangle-list'
});
Notes
- Wrong offsets raise no error, so geometry silently reads the wrong attribute.
- Editing the CPU array after upload does nothing until write() or setGeometry is called.
English edition written for Atlaslog. Code is taken from the original Chinese page and runs unchanged.
Atlaslog (2026). Geometry and buffer layouts. https://www.jingweizhi.com/en/lumagl/tutorials/geometry-buffers.html (accessed 2026-11-03).