Cut draw calls in Babylon.js with InstancedMesh
Use InstancedMesh to render many copies of one geometry with fewer draw calls, and verify the savings in the Babylon.js Inspector.
21 Jul 2026, 09:50 UTC

The problem: one draw call per tree
If you add 1,000 individual meshes to a Babylon.js scene-say, trees in a forest or crates in a warehouse-the engine may issue one draw call for every mesh. Even when every mesh uses the same geometry and material, the CPU still prepares and submits each draw separately. On mobile or lower-end GPUs, that overhead can drop the frame rate before geometry or shading becomes the bottleneck.
The useful takeaway: Babylon.js InstancedMesh lets you share one geometry and one material across many world matrices. The GPU draws all instances in fewer draw calls, while each instance keeps its own position, rotation, and scale.
How InstancedMesh changes the rendering path
An InstancedMesh is not a new copy of the mesh. It references the source mesh's geometry and material, then stores a separate world matrix for each instance. Babylon.js submits the instance data to the GPU in an instancing buffer, and the draw call renders all instances at once. Instancing is used with WebGL 2 and WebGPU backends, though exact API behavior and limits vary by Babylon.js version, browser, and driver.
For cases where you only need position, rotation, and scale per instance-and you do not need separate mesh nodes-Babylon.js also offers thin instances, which are lighter than full InstancedMesh objects. Thin instances are worth considering for very large crowds or particle-like visuals.
Worked example: rendering 1,000 spheres
Run this in your scene setup code, after the engine and scene exist. Replace sourceMesh with the mesh you want to repeat.
// Blueprint mesh; hidden from the scene
const sourceMesh = BABYLON.MeshBuilder.CreateSphere('source', { diameter: 2 }, scene);
sourceMesh.setEnabled(false);
const instanceCount = 1000;
// API shape varies by Babylon.js version; verify against your installed version.
const instancedMesh = sourceMesh.createInstances('crowd', instanceCount);
for (let i = 0; i < instanceCount; i++) {
instancedMesh[i].position = new BABYLON.Vector3(
(Math.random() - 0.5) * 50,
0,
(Math.random() - 0.5) * 50
);
}
This keeps one sphere geometry in memory and sends 1,000 world matrices to the GPU. Do not rewrite every instance matrix from JavaScript each frame until you have measured the cost; that update loop can become a CPU bottleneck.
Verify the savings before you ship
- Open the Babylon.js Inspector on your scene. Run
scene.debugLayer.show()in your app's JavaScript context after scene creation. - Record the draw-call count with individual meshes, then repeat with
InstancedMesh. - Compare frame time in the browser's performance tools on a target device, not only your development machine.
Expect fewer draw calls proportional to the instance count. Frame time may not drop linearly because CPU updates, shading, and fill rate still matter. Treat any specific numbers as version- and device-dependent until you measure them yourself.
Trade-offs and limitations
- No per-instance materials natively. All instances share the source material. Varied looks require texture atlases, vertex colors, or custom attributes.
- Per-instance animation is limited. Animating each instance differently usually means updating matrices on the CPU or using GPU-driven techniques.
- Some features behave differently. Advanced morph targets and certain post-process effects may not work as expected on instanced geometry.
Rollback
If you need per-instance materials or per-instance animation, revert to individual meshes or thin instances. Remove the InstancedMesh and re-enable the source mesh, or replace it with individual Mesh objects for the affected objects.
Closing
Use InstancedMesh when you render many copies of the same geometry and material, and verify the draw-call reduction in the Inspector. Start with static or slowly moving instances, measure on target hardware, and only move to per-instance CPU updates after you have confirmed they are not the new bottleneck.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.