feat: underpass overpasses carry the chapter transitions
@@ -44,3 +44,14 @@ npm run test:browser -- tests/browser/visual-regression.spec.ts
|
||||
- [ ] Review on the physical iPhone 13 and Pixel 6 during `physical-drive.v1`.
|
||||
|
||||
No unsupported engine, physical device, or unpublished project-media result is represented as passed.
|
||||
|
||||
## Underpass shade (chapter boundaries)
|
||||
|
||||
Every chapter boundary is an overpass deck the car drives beneath (`src/scene/world/underpass.ts`, pure rules in `src/journey/underpass.ts`). While the deck is overhead it dims the sky, the fog and the sky-lit road and terrain terms. By construction:
|
||||
|
||||
- **One dark-light cycle per boundary.** The shade follows the deck's distance from the camera: it rises once as the deck arrives and falls once as it leaves. Scrolling back reverses the same single cycle.
|
||||
- **Maximum dip 35%.** The shade multiplier never goes below 0.65 (`SHADE_PEAK = 0.35`). The headlight throw, lamps and HUD are not dimmed.
|
||||
- **Edges of at least 300 ms.** The shade is slew-limited: 0 to the 35% peak, or back, takes at least 300 ms (`SHADE_EDGE_SECONDS`), however fast the scroll.
|
||||
- **A latch of at least 1 s.** Whether a pass shades at all is decided once, as the deck enters the band, and a pass starting within 1 s of the last shaded pass gets no shade (`SHADE_SPACING_MS`). Brisk scrolling (drive speed above 0.5, the exit sign's own gate) and explicit navigation never shade: the deck goes by without dimming or sound.
|
||||
|
||||
The worst case is therefore one shade cycle per second, at most **1 Hz**, well under the three-per-second limit, and each cycle is a 35% dip with soft edges, below the general-flash luminance pair the automated method counts at large area. The low tier draws the deck without any shade. Static, reduced-motion and data-saver visits get no scene, so nothing is added there.
|
||||
|
||||
@@ -71,3 +71,11 @@ Run: `npm run build:preview` then serve `dist` (dev server shows a blank page).
|
||||
- **Verdict: SHIP** (Fable, hardware GL 1440x900, fresh context): beats land on the spec clock (lamps +0.60, rolling +1.00, sweep +1.05, attribute removed +4.5 s); the dissolve is one exposure pull (the poster darkens with the canvas fade, frame luminance 47.7 → 28 with no step over 15 per 200 ms); rAF p50 16.7 / p95 16.8 ms after the first frame. Fixes made during review: (1) the ignition clock no longer counts the first-frame shader stall, so the cold hold is a real 0.6 s; (2) the poster dims with the dissolve instead of a bright image giving way to a dark one; (3) the hero name is unlit until the sweep (the lamp's idle drift pre-lit letters the hold then darkened); (4) every program is compiled in frame 0 behind the poster by a warm render of the whole scene (hidden objects visible, culling off) through the real post-processing pipeline. renderer.compile() keys programs for the screen and never matched the composer's linear targets, so the car, the sign and the streaks each compiled on first sight: 230-280 ms stalls on the first scroll, which tripped the 250 ms catastrophic-frame downgrade and rebuilt the scene mid-opening (a 350 ms freeze and a brightness pop). After the fix no long task follows the first frame in any scenario; the first scroll cuts cleanly in 0.4 s.
|
||||
- **Known weaknesses:** the first frame now lands ~1.7-1.9 s after navigation on a cold GPU (all ~60 programs compile behind the poster in one 1.2 s task; the poster holds, nothing is blank); clicking a nav link inside the opening fires the pre-existing exit-sign flare, one bright frame (mean 80/255) on arrival; the phone opening is quieter (no hero sweep on coarse pointers); the short form's road start is a small 5-point dip in luminance before cruise.
|
||||
- Screenshots: docs/overnight/round8/ (01 long contact sheet 1.5-6.0 s, 02 cold frame, 03 lamps on, 04 rolling + sweep, 05 short form, 06 early-scroll cut sheet, 07 phone 390x844).
|
||||
|
||||
## Round 9: UNDERPASS (chapter transitions)
|
||||
- **What:** every chapter boundary is an overpass deck (exits 02-08, 'EXIT 0N' face plate in the exit accent). It rises out of the haze once the exit sign has fired, holds behind the sign while it comes in, and passes over the camera as the next heading crosses the line; the cut happens in its shadow. The sky, fog and the sky-lit road/terrain terms dip at most 35% (edges >= 300 ms, latched once per pass, >= 1 s apart), three sodium strips and a road pool wash amber, the palette settles x4 under the deck, html[data-underpass='under'] tints the HUD label, and a 600 ms noise swell plays if the soundtrack is audible. Scrolling back re-emerges under the same deck. Brisk scrolls and nav long-scrolls get the structure only. Low tier: deck and strips.
|
||||
- **Build:** journey/underpass.ts (pure), scene/world/underpass.ts, audio/underpass-pass.ts (lazy); environment.ts, palette.ts (dampPalette moved here, rate arg), road.ts, terrain.ts, world.css, bundle-budgets.mjs (lazy chunk class), flash-analysis.md. 872 tests (75 files), initial JS unchanged (+6 B gzip hash noise), CSS +50 B gz, scene chunk +2.8 KB gz.
|
||||
- **Deviation:** deck clearance 22, not 14: the docked exit sign's top edge stands 14-20.4 m above the road at 1440x900.
|
||||
- **Verdict: SHIP** (Fable, hardware GL 1440x900 high tier, wheel-driven passes, frames every ~100 ms): the deck is big, reads as a concrete overpass (parapet, soffit, piers, three strips) and the plate is legible from mid-distance; the sign/deck hand-off is clean (the deck holds in the haze until the sign has passed, and on a brisk approach it sits behind the sign, never through it); the shade beat is one slow dip and release with no step over 22/255 in frame mean (sky band <= 45) at any of Start->Profile, Profile->Experience, Infra->Builds, Builds->Additional, Toolkit->Contact; reverse scroll re-emerges under the same deck (shade latches again, 1 s apart); brisk and nav-jump passes get the structure and no shade/sound; reduced motion renders the static poster with nothing; 1024x700 (medium) shades, 390x844 (low) shows deck+strips only; rAF p50 16.7 / p95 16.7-16.8 ms in every serial run, 0-1 frames over 34 ms, no console errors. Fixes made during review: (1) DECK_PASS_Z 30 -> 25 (the chase camera's z): the deck had gone overhead ~5% of the gap (~1 s at a slow scroll) before the HUD cut, now the cut lands ~0.5 s after 'under' sets, in the deck's shadow; (2) STRIP_GLOW 2.4 -> 1.3 and POOL_GAIN 1.6 -> 1.1: the strips crossed the 0.85 bloom threshold and washed the frame then dropped (sky band 146 -> 32 in one step at Contact), now the strips read as sodium tubes without a flash; (3) plate 11x2.75 -> 16x4.2 over the deck face + parapet, 168 px type, 14 px accent bars: 'EXIT 0N' is readable at z ~ -100 instead of only in the last 30 m; (4) pier shader: 2.6 m form lines, grime at the base and the sodium pool bouncing up the lower faces, so the close pier is poured concrete, not a flat slab.
|
||||
- **Known weaknesses:** the pier at x 16 crosses the left edge of the Selected-builds billboard (stilt at x 17) in front of it for ~6 m of travel, and one expressway lamp head pokes past the right pier at Infra->Builds (both brief, both read as foreground structure); the Contact deck is lit by the dawn sun and reads paler than the night decks (intentional, but less massive); a moderate approach walk can set data-underpass for ~50 ms once before the real pass (hidden by the 0.3 s HUD colour transition, no visible effect); the low tier never shades, so phones get the structure without the beat; `portfolio-underpass-frame` events only exist in test builds, so the review read html[data-underpass] and screencast frames instead.
|
||||
- Screenshots: docs/overnight/round9/ (01 EXIT 02 rising behind the docked sign, 02 under the deck with strips and piers, 03 EXIT 03 overhead at the cut with the amber HUD label, 04 EXIT 08 at dawn into Contact, 05 EXIT 05 pier against the Selected-builds billboard, 06 phone 390x844 low tier, 07 contact sheet of the Profile->Experience pass 20.5-25.5 s).
|
||||
|
||||
BIN
docs/overnight/round9/01-exit02-rising-behind-sign.webp
Normal file
|
After Width: | Height: | Size: 139 KiB |
BIN
docs/overnight/round9/02-exit02-under-deck-strips.webp
Normal file
|
After Width: | Height: | Size: 126 KiB |
BIN
docs/overnight/round9/03-exit03-overhead-at-cut-amber-hud.webp
Normal file
|
After Width: | Height: | Size: 128 KiB |
BIN
docs/overnight/round9/04-exit08-dawn-contact.webp
Normal file
|
After Width: | Height: | Size: 135 KiB |
BIN
docs/overnight/round9/05-exit05-pier-and-billboard.webp
Normal file
|
After Width: | Height: | Size: 123 KiB |
BIN
docs/overnight/round9/06-phone-390-low-tier-deck-only.webp
Normal file
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 201 KiB |