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>
5.8 KiB
Glow-Up (Lane A / engine) — Handoff
Brief: docs/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)
- Tiles 16 → 32 px.
NearestFilterchunkiness 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 cellaTile = (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 forply_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)
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), sofastquality never allocates it.render()picks composer-vs-direct internally; callers keep callingrender()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 — destructure
setBloom; in the MenuonApply:setBloom(s.bloom && s.quality !== 'fast'); addedsetBloom+setEmissiveBoostto thewindow.TURNCRAFTdev handle (used for cine screenshots and fps benchmarking). This file is shared with the Workshop brief, which added its owninteraction.*/jumpScalelines — the edits are disjoint. - src/ui/Menu.ts —
bloom: booleaninSettings(defaulttrue), 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
pcbfloor 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.tsexists; the booth logsscreen-print decals: 13 draw calls (budget < 25)on boot.CH 1–4, tick marks,TURNCRAFT-800, crossfaderA/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 fromsrc/fx/decals.ts:348for the workshop session to wire intoplatter.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.