TURNCRAFT/docs/GLOWUP_A_handoff.md
jing 9c668d340c Headshell Workshop + Glow-Up phase: assembly minigame, art pass, review fixes
- Workshop (WORKSHOP_CARTRIDGE): five-stage cartridge assembly at Deck A —
  seat/square, crimp four tag-wires, torque screws, ride-the-arm counterweight
  balance, needle-drop diagnostic with per-fault audio + scope. Relay-synced
  (per-field co-op merge: held screw + carried wire survive remote state).
- Glow-Up (G1-G5): 32px atlas with per-voxel variants, selective LED bloom
  (quality-gated), screen-print decal system + party flyers, mixer/PCB worldgen
  density pass, record groove-sheen side texture.
- 10 confirmed multi-agent review fixes, incl. co-op screw-stomp soft-lock,
  ride-snap collider-identity (magnet feet / eaten record-fling), workshop SFX
  exact-match map (rca_seated hijack), beam ride colliders to the head,
  double-crimp guard, WIRING INCOMPLETE diagnosis mode, skate-abort timer,
  completedState wiring, per-tick material churn, trackingHeavy platter drag.
- Crossfader playtest fix: slew-limited sled (3.4 v/s) + ribbed grip caps with
  amber index — the sled reads as a heavy handle, not a teleporting wall.
- Demo harnesses: machinesDemo hold-key wiring, playerDemo seesaw phase
  continuity, audioDemo incomplete fault button.
- Workshop sync: exact 1.0 screw endpoint gets its own emit signature.

Verified: typecheck + vite build clean, live solo quest smoke, two-client
co-op relay smoke (simultaneous torque, no rewind, exact convergence).

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

107 lines
5.5 KiB
Markdown
Raw 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 (NOT done — for whichever lane picks it up)
The brief assigns these to the same pass; this session scoped to the engine-owned
G1/G2 only. None are started:
- **G3 screen-print decal system** (`src/fx/decals.ts` + worldgen anchors):
`CH 14`, tick marks, `TURNCRAFT-800`, deck labels, socket numbers, party flyers.
`src/fx/decals.ts` does not exist yet.
- **G4 worldgen density pass** (`src/worldgen/buildBooth.ts`, additive only):
mushroom knob caps, doubled knob rows, panel seam grooves, PCB IC pagodas,
ribbon-cable walls, alley/vent amber pips. Must stay deterministic, build < 800 ms,
anchors untouched.
- **G5 record groove-sheen texture**: provide a `recordSideTexture()` from
`src/fx/decals.ts` for the workshop session to wire into `platter.ts`
(do **not** edit `platter.ts` it is workshop-owned).
The G1 atlas already carries the emissive plumbing G4's LED pips need, and `setBloom`
is live, so G4's new `led_*` blocks will bloom for free.