instanced rendering
VoxForge draws big components as one InstancedMesh per material instead of one mesh per voxel. This benchmark times both paths in plain three.js, on your GPU.
run it
Pick a voxel count and run both modes. mesh gives every voxel its own mesh, geometry and material, which is what React Three Fiber builds for each voxel in components under 512 voxels.instanced groups the voxels into one InstancedMesh per material (8 here), as VoxForge does from 512 voxels up. Picking still hits single voxels, through instanceId; the demo casts the same 200 rays in both modes and counts how many hit the same voxel.
your gpu > starting…
The full sweep runs every size with 3 trials, like my recorded run; it takes minutes, longer on slower GPUs. Large per-voxel runs can freeze the page for several seconds at a time. Keep this tab in front while it runs.
> ready
| voxels | draw calls mesh → instanced | frame ms mesh → instanced | faster | identical picks | my rtx 5090 frame ms |
|---|---|---|---|---|---|
| Nothing run yet. | |||||
my results
Recorded 2026-10-23 on my NVIDIA GeForce RTX 5090 (ANGLE, Direct3D 11). Medians of 3 trials; every pick matched (200/200) at every size.
| voxels | draw calls mesh → instanced | frame ms mesh → instanced | build ms mesh → instanced |
|---|---|---|---|
| 512 | 512 → 8 | 1.2 → 0.039 | 5.8 → 1.4 |
| 4,096 | 4,095 → 8 | 9.8 → 0.050 | 32.0 → 1.1 |
| 16,384 | 16,384 → 8 | 55.1 → 0.131 | 112.2 → 2.8 |
| 32,768 | 32,768 → 8 | 135.4 → 0.219 | 222.8 → 4.6 |
| 65,536 | 65,536 → 8 | 279.5 → 0.436 | 475.0 → 11.4 |
At 4,096 voxels one voxel was culled from the per-voxel view, so that row shows 4,095 draw calls.
method
- A solid block of voxels on a 32-wide footprint, 8 materials assigned with a fixed seed, with the camera pulled back so the whole block is in view.
- VoxForge's editor lighting (ambient 0.65, a shadow-casting sun at 1.45), soft shadows, and the app camera's direction and 42° field of view, rendered at 1280×720 whatever your screen.
- Frame time: batches of renders that end in a
readPixelssync, each batch sized to about 0.5 s, 7 batches per trial.gl.finish()alone doesn't reliably wait for the GPU under ANGLE. - Draw calls: the main pass's, from
renderer.info; the shadow pass isn't counted in either mode.
This measures the three.js scene graph only, not the whole app. It leaves out React and R3F reconciliation and pointer events, which add cost mainly to the per-voxel path. Your numbers depend on your GPU, browser and graphics backend, so they won't match mine exactly.