Skip to content

Implement the scene plugin #99

Description

@dvoyni

Implement scene/spec.md — the declarative 3D rendering plugin, plus the m, gfx, wgpu and canvas changes it cannot be correct without, plus the seven acceptance demos in cog-examples.

This is the implementation effort that follows #1. That issue is the wayfinder map whose resolved tickets produced the spec; this one tracks building what the spec describes. Deferred and out-of-scope work hangs under #29 instead and is not part of this effort.

The spec is the contract the implementation is judged against. Where a ticket and the spec disagree, the spec wins — and if the implementation has to deviate, that gets recorded rather than quietly absorbed.

How to work this

Every sub-issue is labelled ready-for-agent and carries native blocked_by edges. Work the frontier: any ticket whose blockers are all closed. There is no assigned order beyond that.

Nothing here is a horizontal layer slice. Each ticket cuts a narrow but complete path and is verifiable on its own — by a test, by a running demo, or by a captured frame — with the two deliberate exceptions noted under Wide refactors below.

Phases

Roughly, though the dependency graph is the real authority:

Phase Tickets What it delivers
m foundations #59, #60, #61 3D matrix and projection math, bounds/frustum/rays, linear colour constructors
gfx/wgpu capability #63, #64, #65, #66, #67, #68, #69 formats, samplers, 3D pipeline state, explicit passes, the linear frame buffer, storage reflection
Colour migration #62, #70, #71, #72 expand → canvas sRGB → delete the bare constructors → adjudicate the visual shifts
Scene core #73, #74, #75, #76, #77, #79, #80, #81, #82, #84 the plugin, the first pixel, PBR, culling and sorting, debug shapes, helpers, lights, passes, meshes, instancing
glTF #85, #86, #87, #88, #89, #91, #92 assets, loading and residency, node selectors, overrides, the lookup facade, skinning, morphs
Demos and docs #78, #83, #90, #93, #94, #95, #96, #97, #98 the seven acceptance demos, the web build, README and instructions

The tracer bullet is #74 — a camera and a box, deliberately unlit. It is the narrowest complete path through every layer, and the bundled PBR is split out into #75 so the first pixel is not gated on the BRDF.

Wide refactors

Two changes have a blast radius no vertical slice survives, and both are sequenced expand → migrate → contract rather than forced into a tracer bullet:

  • Explicit render passes. #66 adds the pass API beside the implicit default pass so canvas keeps working; #67 migrates canvas onto it and deletes the implicit pass.
  • The colour migration. #61 adds the linear constructors beside the bare ones; #70 does canvas's sRGB atlas and the key-colour re-derivation; #71 deletes NewColor/NewColor8 and classifies all ~57 sites across all three trees by hand. Both consumers replace to the working tree with no version pin, so that sweep is atomic by construction.

Only those two tickets are not independently green, and each is green again the moment its successor lands.

Acceptance

go test ./cmd/scene/... is the one command this effort runs. The assertions live in _test.go files beside each demo and run with no GPU, because culling, sorting and packing all happen in the update-thread flush and the result is published as Passes(dst []PassView) including the frustum.

Everything a number or an ordering can catch is an assertion. Everything only eyes can judge is one falsifiable sentence per demo. The two visible criteria worth naming, both on cameras and both chosen over assertions on purpose — a sign error in the Y flip is exactly the bug an assertion written by the author of the flip will happily confirm:

  • the nameplate stays glued to the cube in both viewports, and disappears rather than mirroring when the cube passes behind the camera
  • clicking a cube tints that cube and no other, including through the composited texture camera

Desktop is the acceptance bar, with animated (#94) designated the web canary — it touches the most storage-buffer bindings, the budget has no spare, and a single unbound binding silently kills the whole frame with no error anywhere.

There is no CI, no testdata/, no golden images and no frame readback in this repo, and none of that is built here. Golden-image acceptance is #54.

Three things to know before starting

  • #58 is a real gate, not a note. The storage-buffer budget is eight of eight against the browser core-adapter floor, with zero headroom, because every reflected binding is emitted Vertex|Fragment unconditionally. It blocks skinning (#91) and morphs (#92), and an implementation must not add a ninth.
  • #68 carries the migration's one falsifiable claim — a pixel-identical frame — and exists to be the bisect point between "the present pass is wrong" and "the migration looks different". Routing canvas's currently gamma-encoded output through an sRGB frame buffer and an OETF present pass may well turn out to double-encode; discovering that there is the ticket doing its job, and its acceptance criteria allow either outcome so long as the resolution is recorded.
  • #62 must land before #71 starts. Every judgement the colour migration defers is triggered by looking, and the existing canvas suite is colour-blind — every colour literal in it is fixed-point, so it neither breaks nor verifies. Without captured "before" frames those triggers fire against a memory of how it used to look.

Edges worth revisiting

Three dependency edges are defensible rather than forced, and are the levers if this needs to parallelise harder:

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions