Rust voxel sandbox (wgpu + wasm + axum multiplayer)
Diagnosis (from earlier tick/toc data + literature review):
- Page load was dominated by the per-vertex sky_visibility bake
inside build_chunk_mesh: 8 cosine-weighted hemisphere rays × ~15
voxel DDA steps × HashMap-backed World::get_block per ray, per
vertex. ~100ms/chunk × 289 chunks = ~29s on the main thread.
- The greedy mesh algorithm itself was fine; the bake was the bug.
- State of the art (cgerikj's binary greedy meshing) runs 50-200µs
per chunk, but that assumes Lysenko's cheap local AO, not a
global hemisphere ray cast. Our problem was the wrong primitive,
not the wrong algorithm.
Fix (this commit):
- world.rs gains a HeightMap type — per-chunk 16×16 i32 array of
topmost-solid-Y. Cached in World.heightmaps, invalidated by
set_block per affected chunk.
- sim/lighting.rs gains compute_ambience_fast(): inverse-distance-
weighted 7×7 column scan. ~25 array lookups per vertex instead
of 8 ray casts. The 1/sqrt(r²+1) weighting makes the center
column dominate, so a slab right overhead correctly produces
near-zero sky_vis even though the 7×7 window extends past the
slab's edges. The old compute_ambience stays around (renamed
"slow path" in doc) so the construction-invariance test still
has the rigorous reference to compare against.
- mesh.rs: warm_heightmaps_around(chunk) pre-populates the
heightmap cache for this chunk + 8 neighbors before build_chunk_mesh.
build_chunk_mesh calls compute_ambience_fast.
- render/mod.rs::rebuild_chunk takes &mut World now (to warm
heightmaps) and tightens its tick/toc threshold to 0.5ms so the
fast path is observable in telemetry.
Progressive chunk loading (this commit):
- App.pending_chunk_builds: VecDeque<IVec3>, populated at init
spatially sorted closest-first so the chunk under the player
meshes first and the distant horizon fills in last.
- App::tick now drains the queue at a 12ms-per-frame budget.
Browser stays responsive; world appears immediately and
completes over ~2s.
Measured (locally, fresh browser cache):
Before: window.voxel_game ready in ~32,000 ms
After: window.voxel_game ready in 367 ms (~90× faster)
Chunk-build time: 100ms → < 0.5ms each (sub-threshold for logging)
Tests: 63 passing. Native + wasm release clean.
Deferred to its own session: binary greedy meshing (cgerikj-style
64-bit bitmask scan). After this commit it's the next bottleneck
worth attacking; not before.
|
||
|---|---|---|
| server | ||
| src | ||
| test | ||
| web | ||
| .dockerignore | ||
| .gitignore | ||
| ARCHITECTURE.md | ||
| build-web.sh | ||
| Caddyfile | ||
| Cargo.lock | ||
| Cargo.toml | ||
| DEPLOY.md | ||
| docker-compose.prod.yml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| run.sh | ||