Draw call

One 'GPU, draw this' command. Each costs CPU time, so 3000 separate objects stutter even when the scene looks simple.

why is it slow when there's lots of objectsthe count thing that makes 3D lagtoo many objects in the scenewhy does every mesh add rendering overheaddrawcallthe number in the stats panel that should be lowbatching problemwhy does my 3D scene stutter with hundreds of models

See it

Live demo coming soon

What it is

A draw call is one instruction from the CPU to the GPU: 'render this chunk of geometry with this material and this state'. Each one carries setup overhead on the CPU side, and the browser adds its own validation on top in WebGL. Pile up enough of them and the CPU becomes the bottleneck, with the GPU idling while it waits to be told what to do. That is not the same as saying the GPU is never the limit: fill rate, shader cost, texture bandwidth, and overdraw put plenty of WebGL scenes firmly on the GPU side, so profile both ends before picking a fix. Rough field guide: a few hundred draw calls per frame is comfortable, a couple thousand starts hurting on mid-range phones.

Count goes up with the number of separate mesh-plus-material pairs, not with triangle count. This is why one 200k-triangle model often outperforms 400 tiny models that total 50k triangles. The fixes are all about doing more per call: instancing for repeated objects (one call for ten thousand trees), merging static meshes that share a material, and packing textures into an atlas so more objects can share one material.

Gotcha: people optimize the wrong number. Before you decimate meshes, open the renderer stats panel and read the actual call count. And watch the sneaky multipliers: every shadow-casting light re-renders the scene into its shadow map, and every post-processing pass adds another full-screen draw over the whole frame (not a second run through your geometry, but real pixels all the same), so 'one' scene can quietly cost several passes.

Ask AI for it

Cut the draw calls in this Three.js scene. Replace repeated meshes with InstancedMesh (one instanced draw per repeated model, transforms in the instance matrix), merge static geometry that shares a material with mergeGeometries, and consolidate materials by packing their textures into a single atlas. Turn on frustum culling, cap shadow-casting lights at one, and log renderer.info.render.calls before and after so the win is measurable.

You might have meant

instancingtexture atlasfrustum cullingoverdrawmaterial