feat(zoom-to-Earth): true-scale foreground renderer (Plan 01 + polish)#386
Draft
rulkens wants to merge 24 commits into
Draft
feat(zoom-to-Earth): true-scale foreground renderer (Plan 01 + polish)#386rulkens wants to merge 24 commits into
rulkens wants to merge 24 commits into
Conversation
Kept foundation (not a throwaway spike): continuous per-object floating origin (f64 truth on CPU, narrow to f32 at the GPU boundary) so the camera can fly from the cosmic-web view down to a true-scale textured Earth past a few anchors. Refines ADR 0001's discrete-shell stance for the interactive free-zoom case. Captures the readiness audit: the main scene is depthless/additive (opaque bodies need a new depth-tested foreground pass composited via the volume offscreen template), gl-matrix is f32-only (needs f64 mat helpers), and star/planet/earth slot in as new SOURCE_REGISTRY data types seeded like the famous/structures pattern. Precision slice is task 1, kept if green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The gl-matrix → wgpu-matrix migration (#382) provides f64 matrix composition via mat4d/vec3d, so §8 no longer needs hand-written lookAt64/perspectiveZO64/multiply64/translate64/scale64 helpers. Only narrowMat4 (f64 → f32 for upload) remains bespoke. Updated §2, §3, §8, §9, §10, §11, and references accordingly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…LOD+polish) Three sequential plans for the zoom-to-Earth-at-true-scale feature, split by the spec's phases with a shared cross-plan contract so type names/seams stay consistent: - 01 precision slice (Phase 1, the de-risk): scaleUnits + narrowMat4 + f64 MVP compose via mat4d + opaque foreground depth pass + lowered min-distance + debug sphere at Earth's true scale. - 02 earth & anchors (Phases 2-3): star/planet/earth data types + stores + sphere renderers on shared infra (Blue Marble Earth, Sun/Moon/Jupiter/Proxima). - 03 LOD & polish (Phases 4-5): adaptive foreground frustum, apparent-size point<->sphere promotion, fly-to-Earth debug key, ADR 0008, entanglement-radar. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Unit conversions (km/AU/pc/kpc/Mpc/Gpc + ly for copy) derived from a single parsec-in-km base, and the fixed Sun render origin the per-object f64 matrix math is expressed relative to. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…enderOrigin (zoom-to-Earth T3) Composes proj*view in wgpu-matrix mat4d (f64), with eye/target taken relative to renderOrigin before lookAt. With renderOrigin=[0,0,0] it narrows to the existing f32 computeViewProj; the f64 path is what survives Earth-at-1-AU scale. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… (zoom-to-Earth T4) Composes the full per-body MVP in wgpu-matrix mat4d (unit sphere translated to bodyPos-renderOrigin and scaled by radiusMpc) and narrows the product to f32. Guard tests prove the de-risk: at parsec scale the f64 compose-then-narrow holds a body-radius feature to ~7e-7 radii while narrowing view and model separately loses ~376 radii. (Negative-test geometry corrected from 1 AU to parsec scale, where cancellation actually bites — see plan note.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…s (zoom-to-Earth T5) Unit-radius positions, equirectangular uvs (seam column duplicated for clean texture wrap), CCW outward-facing triangle-list indices. Shared by the debug sphere now and the Earth/planet/star renderers later. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…zoom-to-Earth T6) Full-res rgba16float color + depth32float depth target for the opaque foreground, and a fullscreen pass compositing it OVER the additive HDR backdrop (src-alpha / one-minus-src-alpha), unlike volumeUpsample's additive blend. Not yet wired into the frame loop (Task 10/11). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Shared SphereUniforms { mvp } + clip_from_local(mvp, localPos) helper (mvp
passed as a param, not captured), plus a flat lat-long-shaded debug-sphere
vertex/fragment emitting straight opaque alpha for the OVER composite.
SphereUniforms at @group(0)@binding(0); position @location(0) vec3 stride 12.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…h pass (zoom-to-Earth T8) Uploads uvSphereMesh once (pos VBO + index IBO), explicit group0/binding0 SphereUniforms layout, depth32float depth-test (write on, less), rgba16float opaque colour, CCW/back-cull. draw(pass, mvp) writes the f32 MVP and draws indexed. satisfies Renderer. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ng (zoom-to-Earth T9) deriveFrameContext now composes the f64 foregroundVp (computeForegroundViewProj relative to RENDER_ORIGIN_MPC) once per frame and carries foregroundNear/Far (a coarse Plan-01 cam.distance heuristic; Plan 03 swaps in foregroundFrustum) + renderOrigin. Existing ready-ctx test fixtures updated for the four new required fields (neutral placeholders; the foreground pass isn't wired yet). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…Earth T11)
EngineGpuHandles gains foregroundOffscreen / foregroundComposite /
debugSphereRenderer (nullable). initGpu builds them after the existing
renderers ('rgba16float' color + 'depth32float' depth); runFrame resizes the
offscreen alongside postProcess/volumeOffscreen; engine.destroy() releases all
three. Not yet drawn (encodeForegroundPass is the next task). vite build green:
the foreground WESL links cleanly now that it is in the import graph.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ody seed (zoom-to-Earth T12) MIN_DISTANCE_MPC 0.05 -> 1e-17 Mpc so the camera can sit just off Earth's surface; the focus-on tween end (0.15 Mpc) sits far above the new floor so clampDistance never ratchets it. DEBUG_SPHERE_BODY seeds Earth at true size (6371 km) and a 1-AU position for the foreground pass to draw (Plan-01 stand-in; Plan 02 replaces it with BodyStore.earth). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…to the frame (zoom-to-Earth T10) Two-step pass on the shared encoder: render DEBUG_SPHERE_BODY into the foreground offscreen (own depth, cleared) via composeBodyMvp, then OVER-composite it onto ctx.postProcess.view (loadOp 'load', preserving the additive backdrop). Slotted into both renderFrame branches after the HDR mega-pass and before tonemap, so Earth stays inside the HDR/tonemap pipeline. Self-gates on the nullable handles. destroyReachability test gains vi.mocks for the three foreground factories. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ew fixes) Teaching comments in the f64/f32 seam stated 1 AU as ~4.8e-9 Mpc (off by 1000x; actual ~4.85e-12) and one conflated the AU distance with Earth's radius (~2.06e-16 Mpc). Also: narrowMat4 docblock said row-major (wgpu-matrix/WGSL are column-major); renderFrame's pass-order list omitted the foreground composite; the cancellation-guard test comment conflated the raw VP-translation error with the bounded ndcErrorMpc metric. Comment-only; suite + build unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…metry correction All 13 tasks checked off through the automated gate; records the parsec-scale correction to the catastrophic-cancellation guard test and the reorder note (T11/T12 before T10). Visual gate (Task 13) remains open pending on-screen review. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The camera focuses on the Sun (render origin), but the only debug sphere was Earth — seeded ~1 AU off-axis and 109x smaller — so nothing rendered where the camera lands. Seed a Sun sphere at the origin as a visible landmark + scale reference. Drawing two spheres surfaced a latent bug: debugSphereRenderer wrote one shared MVP uniform per draw, which the queue.writeBuffer/submit ordering collapses onto the last body. Switched to per-sphere dynamic uniform offsets so each renders with its own matrix in one submit. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…cale formatDistance bottomed out at kpc, so zooming to the Sun/Earth showed a useless "0.0000000048 kpc" label. Continue the ladder below a kiloparsec: pc/ly (parsec family), then a bare AU (solar-system scale), then a bare km (planetary surface) once inside an astronomical unit. The light-year companion is dropped below 1 pc, where a fraction of a light-year is no more intuitive than a fraction of a parsec. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The true-scale foreground spheres are sub-pixel at almost every zoom, so locating Earth by eye is hopeless. Add 'Sun'/'Earth' captions anchored to each body's world position. They can't ride the existing label path: the main projection's near plane is pinned at 0.01 Mpc, and at solar-system zoom the bodies sit ~1e-13 Mpc from the camera — inside that near plane, so the normal labels would clip them. A label renderer draws with one view-projection, so a second LabelRenderer instance (foregroundLabelRenderer) drawn with the adaptive foregroundVp in its own UI pass is the natural split. Gated on cam.distance < 1 kpc so the captions only appear during the descent and don't clutter the galaxy view. This foreground-label seam is reused by Plan 02's real planet labels. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Sun/Earth captions used a fully-opaque black outline, which the premultiplied-OVER composite renders as a hard black ring rather than a shadow. Match the shared label convention (10%-alpha black, em-frac 0.16). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… disc The procedural impostor is calibrated to be viewed from outside the disc. Flying down toward the Sun left it hanging in front of the solar-system view like a billboard you'd walked behind. Add milkyWayApproachFadeAlpha — a near-side smoothstep (full beyond ~40 kpc, gone by ~8 kpc, the Sun's galactocentric radius) — and multiply it into the existing fadeAlpha channel, mirroring how clusters dim once you're inside their radius. The far-side milkyWayFadeAlpha is unchanged; the pass now gates and draws on the product of the two. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…labels Galaxy-level labels drew on top of the Sun disc because the foreground spheres composited into HDR before tone-map, while labels draw post-tone-map on the swap chain. Move the foreground composite to AFTER the UI overlay: encodeForegroundPass now only fills the foreground offscreen, and a new encodeForegroundOver tone-maps it (same curve as the scene, via shared toneMapDefaults + lib/tonemap.wesl) and OVER-composites it onto the swap chain, then draws the Sun/Earth captions in the same pass so they land on top. Galaxy labels / marker-lines / selection rings behind an opaque body are now truly occluded by it, and a future translucent atmosphere will tint them rather than hard-mask them. foregroundLabelsPass leaves UI_PASSES (it moves into the new pass); foregroundComposite retargets to the swap format and gains the tone-map uniform. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
skymap | 0b184eb | Commit Preview URL Branch Preview URL |
Jun 30 2026, 12:57 AM |
rulkens
added a commit
that referenced
this pull request
Jul 3, 2026
The 2026-07-02 powers-of-ten architecture review re-checked this spec's premises against current main (post #394/#396) and found four stale spots: - Migration table: add clipPathDebugPass (UI_PASSES member since the tour work) and note drawPickDebugOverlay as a debug composite step — main already has three hand-rolled composites before #386 adds its fourth. - FrameStep program: the volume prepass + flow compute are nested inside BOTH HDR encoder branches today; the program lifts them, and the executor owns the single/split timing fork as an execution strategy (TIMED_SLOT_NAMES then derives from the program). - Pick: new prerequisite — camera-for-pick becomes a value from the slab table; the pointSpritesPass byte-snapshot side channel (lastFrameUniformBytes) makes per-slab pick unimplementable. - Phase 2: renderer factories declare targetFormat explicitly; three coexisting initGpu idioms named; GpuContext.format = swap format only. Also: state PR #386 (foreground path) is a draft, not merged; phase-1 merge-order handling; cite the real tone-map curve test. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
rulkens
added a commit
that referenced
this pull request
Jul 6, 2026
Plans (one per spec phase, executed via subagent-driven-development): - 01-compositor: Compositor primitive (all three blends) + the postProcess tonemap repoint; shaders/toneMap/ deleted; curve mirror moves in. - 02-registry-and-program: eight @types/engine/frame types, slabs.ts (NEAR0/COSMO + slabViewOf), ContentLayer conversion of all 14 passes, frameProgram(tone) + strategy executor + derived timing slots, target table + consolidated resize, targetFormat factory cleanup, PassDeps deleted. 11 tasks, green suite at every commit, flip isolated in Task 7. - 03-pick: pick camera becomes a value (lastFrameUniformBytes deleted, full 176-byte re-home table), drawPick rows, per-slab pickProgram, frontmostPick. Also dissolves proceduralDiskRenderer's second camera stash. - 00-index: ordering, locked cross-plan seams, #386 merge-order. Spec correction from plan-time shader verification: volumeUpsamplePass stays a content layer (its 4-tap rotated-grid low-pass is essential grain suppression) and drawPickDebugOverlay stays a bespoke debug renderer (r32uint textureLoad visualisation) — neither is a Compositor consumer. The FRAME program loses the volume→hdr composite step; the volume double-gate knot is fixed by one shared deriveVolumeLiveness projection. Also recorded: the blend→dstFormat constructor mapping (a pass encoder cannot be queried for its attachment format). Backlog: render-graph-restructure item removed (index line + detail file) per the spec's acceptance note — the FrameStep program supersedes it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
rulkens
added a commit
that referenced
this pull request
Jul 6, 2026
…ab model The fold plan executes on the #386 branch after plans 01+02 land: the bespoke foreground wiring (encodeForegroundPass/Over, foregroundLabelsPass, foregroundComposite + shaders, foregroundOffscreen, four ReadyFrameContext fields) dissolves into two ContentLayer rows, one depth-bearing RenderTargetSpec row, the activated NEAR0 slab (origin-relative f64 computeForegroundViewProj), and three appended FRAME steps. #386's deferred visual gate becomes the plan's final gate. Two contract amendments the fold surfaced, both fixed pre-execution: - Compositor alpha semantics are now a column of the blend table (replace → 1.0; over/additive → preserve src alpha, packed as a preserveAlpha uniform derived from the blend). Plan 01's 'over' was premultiplied with a forced alpha-1.0 emit — folding #386's straight-alpha composite onto that would have painted the foreground offscreen over the whole screen. - Depth attachments become target-table + executor data in plan 04 (foreground:0 is the first row to exercise RenderTargetSpec.depth). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
What
The zoom-to-Earth true-scale foreground renderer — Plan 01 (precision slice) plus follow-on polish.
computeForegroundViewProj,composeBodyMvp): composes proj·view·model in double precision and narrows at the GPU-upload boundary, so a body at ~1 AU inside an Mpc-scale VP doesn't lose its position to catastrophic cancellation.Status
Draft — awaiting visual confirmation at solar-system zoom. Plans 02 (Earth + anchors) and 03 (LOD + polish) are not started. Do not merge until the visual gate passes.
🤖 Generated with Claude Code