TURNCRAFT/docs/GLOWUP_A_handoff.md
jing 74482e5693 Glow-up review fix: concentric groove caps on record tiers
Fresh-eyes review of the glow-up found the G5 side-ring texture applied to
whole tier cylinders - linear UVs on the caps rendered as diagonal stripes
across the disc. CylinderGeometry takes [side, top, bottom] materials: sides
keep Lane E's ring texture, caps get a new radial recordCapGrooveTexture()
(machines/util.ts) with ring count scaled per tier radius so groove pitch
stays constant. Also lands the three handoff-doc updates from the phase.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 22:48:32 +10:00

110 lines
5.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Glow-Up (Lane A / engine) — Handoff
**Brief:** [docs/briefs/GLOWUP_ART.md](briefs/GLOWUP_ART.md)
**Scope done here:** **G1 (Atlas v2)** and **G2 (selective LED bloom)** — the two
engine-owned tasks. **G3G5 are NOT started** (see "Remaining" below).
**Status:** ✅ G1 + G2 complete, browser-verified in the real game, typecheck clean,
zero console errors.
---
## What shipped
### G1 — Atlas v2 ([src/engine/atlas.ts](../src/engine/atlas.ts))
- Tiles **16 → 32 px**. `NearestFilter` chunkiness preserved (fract keeps every
sample inside its cell — no bleed, no mip seams).
- **Per-voxel variant system, zero mesher changes.** 4 painted variants per block
laid out in extra atlas columns (`GRID_W = COLS*NVAR = 32`). The material shader
patch hashes each voxel's baked world position (`floor(position - 0.02*normal)`)
→ picks a variant → expands the base cell column. A repeated surface (PCB floor,
plywood wall, brushed metal) breaks up instead of tiling like wallpaper. The
mesher still writes only the base cell `aTile = (id%8, id/8)` — its verified
winding/AO path is untouched. (This is the brief's "shader-patch variant"
fallback, applied to **all** patterns, not just pcb.)
- Pattern rewrites: `brushed` = long directional strokes + scratches (not noise);
`plywood` = long wavy grain, concentric end-grain rings for `ply_edge`;
`pcb` = 4 variants that tile into routed traces + via dots + silkscreen flecks;
`grooves` = concentric arcs + specular sheen line; `led` = smooth radial glow.
- Material polish via roughness only: `0.82 → 0.78` (no env maps, per brief).
### G2 — Selective LED bloom ([src/engine/renderer.ts](../src/engine/renderer.ts))
- `EffectComposer` + `RenderPass` + `UnrealBloomPass` + `OutputPass`.
Tuned `{ strength 0.9, radius 0.5, threshold 0.85 }` so **only emissive
LEDs/strobe/lamps cross the threshold** — lit plywood/metal stays matte.
- **Lazy:** the composer is created only on first `setBloom(true)`, so `fast`
quality never allocates it. `render()` picks composer-vs-direct internally;
callers keep calling `render()` unchanged.
- New API on the renderer: `setBloom(enabled: boolean)`. Composer size/pixelRatio
re-sync on resize and on quality (pixelRatio) changes.
### Wiring (merge points — kept additive)
- **[src/main.ts](../src/main.ts)** — destructure `setBloom`; in the Menu
`onApply`: `setBloom(s.bloom && s.quality !== 'fast')`; added `setBloom` +
`setEmissiveBoost` to the `window.TURNCRAFT` dev handle (used for cine screenshots
and fps benchmarking). *This file is shared with the Workshop brief, which added
its own `interaction.*` / `jumpScale` lines — the edits are disjoint.*
- **[src/ui/Menu.ts](../src/ui/Menu.ts)** — `bloom: boolean` in `Settings`
(default `true`), one checkbox row ("LED bloom (glow — off automatically on Fast)").
---
## Files touched
| file | task | note |
|---|---|---|
| `src/engine/atlas.ts` | G1 | rewritten — 32px, variants, patterns |
| `src/engine/renderer.ts` | G2 | +bloom composer, `setBloom()` |
| `src/ui/Menu.ts` | G2 | +`bloom` setting + checkbox |
| `src/main.ts` | merge | additive: `setBloom` wiring + dev handle |
**Merge points:** `src/main.ts` (shared with Workshop brief),
`src/ui/Menu.ts` (one settings row). `src/worldgen/buildBooth.ts` is listed as a
merge point in the brief but G1/G2 did **not** need to touch it (that's G4).
---
## Verification (ran it in the real game, port 5173)
- Boot: **739 ms build, 467 chunk meshes** (< 600 ✓), zero console errors.
- **Bloom A/B at the mixer** (retina 2560×1440): LEDs (knob caps, VU towers,
fader-alley pips) glow with a soft halo when ON, flat when OFF; plywood floor,
matte-black body, and walls do **not** glow either way **selective confirmed**.
- **PCB Depths**: the `pcb` floor now reads as routed circuitry (traces + vias +
silkscreen), not "green wallpaper"; variant hashing tiles it into a connected grid.
- **Deck platter**: record shows concentric groove rings; brushed-metal plinth reads
brushed; amber spindle lamp + orange strobe rim-pips bloom while the plinth stays matte.
- **fps** (real, `readPixels`-forced GPU sync at 2560×1440, two runs):
- Bloom **OFF**: ~234 / ~249 fps
- Bloom **ON**: ~174 / ~220 fps (bloom overhead 1.5 ms/frame)
- Both comfortably clear the ** 100 fps** budget.
- (rAF is throttled in the headless preview pane, so frame-count fps reads 0 there;
the synchronous per-frame render timing above is the trustworthy measure.)
- `npm run typecheck`: **clean** (exit 0), including the concurrent Workshop edits.
---
## Remaining Glow-Up work — UPDATE (re-checked after G3/G4 landed)
This session scoped to the engine-owned **G1/G2** only. At the time of writing,
G3G5 were not started. **They have since been implemented by another session**
re-verified against the live build:
- **G3 screen-print decals**: landed. `src/fx/decals.ts` exists; the booth logs
`screen-print decals: 13 draw calls (budget < 25)` on boot. `CH 14`, tick marks,
`TURNCRAFT-800`, crossfader `A`/`B`, `PATCH BAY`, and wall party flyers all render.
- **G4 worldgen density**: appears landed (denser/mixed knob clusters + lit
fader-alley pips visible at the mixer face; build still ~752 ms, 467 chunk meshes).
- **G5 record groove-sheen**: `recordSideTexture()` is exported from
`src/fx/decals.ts:348` for the workshop session to wire into `platter.ts`.
Nothing here changes G1/G2. Confirmed on the integrated build: `npm run typecheck`
clean (exit 0) with the Workshop + decal code merged; booth boots with **zero console
errors**; at the mixer the alley pips / VU towers bloom while plywood and the
matte-black body stay matte (**selective bloom still correct** next to the new decals);
Atlas v2's grain/knob detail reads correctly under the new screen-print.
As predicted, G4's `led_*` pips bloom for free through the existing emissive plumbing.