Instanced meshes, draw-call budgets and the profiling workflow we use to keep heavy scenes buttery on mid-range hardware.
PUBLISHED JUL 17, 2026 • 5 MIN READ
Sixty frames per second is not a performance target, it is a deadline. You get 16.6 milliseconds, the browser takes a slice for compositing, and whatever is left belongs to your scene. Most WebGL work that feels slow is not doing too much maths — it is talking to the GPU too often.
Decide the number before you model anything. On mid-range mobile hardware we hold to roughly 150 draw calls per frame; anything past that and the CPU becomes the bottleneck long before the fragment shader does. A budget turns an open-ended optimisation problem into a checklist.
You cannot optimise what you never measured. Open the profiler before you open the shader.
Any geometry that appears more than a handful of times belongs in an instanced mesh. Twelve thousand particles as individual meshes will stall the main thread; the same twelve thousand as one instanced draw call costs about as much as a single cube. The per-instance data lives in an attribute buffer you update in place.
The cheapest frame is the one you never render. Pause the loop when the canvas leaves the viewport, when the tab is hidden, and when nothing in the scene has changed. Users judge a site by its battery drain far more than they admit.