Boosting BabylonJS Scene Performance with InstancedMesh
Learn how BabylonJS InstancedMesh cuts draw calls from thousands to one, boosting FPS for large numbers of identical objects, with a concrete example and trade‑offs.
21 Mar 2026, 22:40 UTC

The Problem: Too Many Draw Calls
When you create many identical objects—such as trees, particles, or grid cells—each mesh generates its own draw call. On a mid‑range GPU a scene with 5 000 separate boxes can easily stay below 30 FPS because the CPU spends most of its time issuing draw calls.
Why InstancedMesh Helps
InstancedMesh stores a single vertex buffer and material, then keeps an array of world matrices—one per instance. Changing an instance’s position, rotation or scaling updates its matrix without creating a new draw call. The GPU draws all instances in one pass, so draw calls drop from N to roughly 1 (plus any overhead for shadows or post‑process).
Worked Example: From 5000 Boxes to One Draw Call
// Create a shared box geometry
const box = BABYLON.MeshBuilder.CreateBox("box", {size: 1}, scene);
// Create the InstancedMesh that will hold 5000 copies
const instances = new BABYLON.InstancedMesh("boxInst", box, scene);
// Optional: enable shadows if you need them
instances.receiveShadows = true;
// Position each instance in a grid
for (let i = 0; i < 5000; i++) {
const x = (i % 70) - 35;
const z = Math.floor(i / 70) - 35;
instances.instances[i].position = new BABYLON.Vector3(x, 0, z);
}
// Force Babylon to update the instance buffer
instances.isPickable = false; // just to trigger internal update
Open the debug layer (scene.debugLayer.show()) and look at the draw call counter before replacing the loop with individual MeshBuilder.CreateBox calls. You should see the count fall from ~5000 to ~1 and the FPS rise accordingly.
Trade‑offs and When to Look Elsewhere
- All instances share the same material; you cannot give each box a different color or texture without extra work (vertex colors, texture atlases, or Thin Instances).
- If you need to change an instance’s matrix every frame for thousands of objects, the CPU work of updating the world‑matrix array can become the bottleneck. In highly dynamic cases consider Thin Instances or GPU‑driven updates via compute shaders.
- InstancedMesh works with PBR, shadows, and physics impostors, but physics updates still require per‑instance synchronization.
Putting It Into Practice
- Verify your BabylonJS version:
console.log(BABYLON.Engine.version)– InstancedMesh exists since v2.5. - Replace static duplicate meshes with an InstancedMesh as shown above.
- Enable the debug layer or use
engine.getFps()to confirm the improvement. - If you need per‑instance color, add a vertex color buffer to the source mesh or switch to Thin Instances.
By moving repetitive geometry into an InstancedMesh you keep draw calls low, free the CPU for game logic, and often double the frame rate on modest hardware.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.