Repository navigation
#542 WebGPU scenery: per-primitive colour + lazy route-progressive GLB loading - #591
Closed
MaximumTrainer wants to merge 2 commits into
Closed
MaximumTrainer wants to merge 2 commits into
MaximumTrainer wants to merge 2 commits into
Conversation
The scenery-mesh pass collapsed every primitive of a GLB into one mesh and painted the whole thing in primitive-0's baseColor, so multi-material models (trunk/leaves, walls/roof/windows) rendered as a single pale block. glTF splits a model into one primitive per material; bake each primitive's colour per vertex and carry it through sceneryMesh.wgsl as a vertex attribute, so parts stay distinct — matching how the React scene binds per-primitive materials. Single-colour callers (boat primitives) omit `colors` and the pass fills every vertex from `baseColor`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q5D9BTXmu7SeMa3LghJD8b
Scenery GLBs were all fetched up-front at attach (a Promise.all over every model), which blocks the first frame and can trip a static-host 503 — the same burst the React scene avoids by chunking its loads. Defer them: plan where each model first appears along the route, then load models from the frame loop as the boat comes within a look-ahead window, capped a few per tick. Course furniture and GLB scenery share one instance-transform map; a model's instances are set the moment its GLB registers, so nothing draws before it is ready and distant scenery streams in as the row progresses. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q5D9BTXmu7SeMa3LghJD8b
Owner
Author
|
Superseded by #594. That branch is built on top of this one (it contains both commits here verbatim) and adds the scenery-density follow-up — real-tier plumbing, biome-density grass colour, and reeds/rocks/cone-stack trees — so the parity work lands as one reviewable PR. Closing this in favour of #594. Generated by Claude Code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two scenery-render fixes found reviewing the WebGPU vs React ride on a real GPU (#542 pre-cutover parity).
1. Per-primitive scenery colour
The scenery-mesh pass merged every primitive of a GLB into one mesh and painted the whole thing in primitive-0's
baseColor, so multi-material models (trunk/leaves, walls/roof/windows) rendered as a single pale/white block — e.g. a landform ridge drawn in a roof colour. The GLB kit is textureless flat-colour PBR by design, and the React scene keeps parts distinct only because three's GLTFLoader binds each primitive to its own material.Fix: bake each primitive's
baseColorinto a per-vertex colour attribute (mergeSceneryPrimitives) and carry it throughsceneryMesh.wgsl, dropping the single-colour uniform. Single-colour callers (the boat scull primitives) omitcolorsand the pass fills every vertex frombaseColor, so they're unaffected.2. Lazy, route-progressive GLB loading
Scenery GLBs were all fetched up-front at attach (a
Promise.allover every model) — a burst that blocks the first frame and can trip a static-host 503 (the same reason the React scene chunks its loads). Now a pure planner (sceneryStreamPlan) works out where each model first appears along the route, and the frame loop loads models as the boat comes within a 400 m look-ahead window, capped a few per tick. Course furniture and GLB scenery share one instance-transform map; a model's instances are set the moment its GLB registers.Tests
sceneryMeshBuffers.test.ts— per-vertex colour baking (regression: not primitive-0 for all), index offset, Uint32 widening.sceneryMesh.test.ts— colour vertex buffer uploaded/synthesized and bound at slot 2.sceneryStreamPlan.test.ts— per-model trigger distances, look-ahead window, cap, exclude-loaded.attach,ac4PortedBehaviorsstill green; fullverify(lint + tsc + unit + coverage) green on push.The GPU-rendered result (colour parity + streaming) is being confirmed on the Intel Gen-9 laptop; this is engine-only, scoped to the scenery pass + route adapter.
Generated by Claude Code