Skip to content

#542 WebGPU scenery: per-primitive colour + lazy route-progressive GLB loading - #591

Closed
MaximumTrainer wants to merge 2 commits into
next/svelte-webgpufrom
claude/project-thread-lddi4g
Closed

MaximumTrainer wants to merge 2 commits into
next/svelte-webgpufrom
claude/project-thread-lddi4g

Conversation

@MaximumTrainer

Copy link
Copy Markdown
Owner

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 baseColor into a per-vertex colour attribute (mergeSceneryPrimitives) and carry it through sceneryMesh.wgsl, dropping the single-colour uniform. Single-colour callers (the boat scull primitives) omit colors and the pass fills every vertex from baseColor, so they're unaffected.

2. Lazy, route-progressive GLB loading

Scenery GLBs were all fetched up-front at attach (a Promise.all over 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.
  • WGSL parse, attach, ac4PortedBehaviors still green; full verify (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

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

Copy link
Copy Markdown
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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants