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>
110 lines
5.8 KiB
Markdown
110 lines
5.8 KiB
Markdown
# 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. **G3–G5 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,
|
||
G3–G5 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 1–4`, 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.
|