feat: daybreak finale turns the contact arrival into a sunrise with a dawn chord
This commit is contained in:
@@ -25,6 +25,8 @@ import { CHAPTER_COMPOSITIONS } from '@/scene/world/composition';
|
||||
import { createCoachworkEnvironment } from '@/scene/world/coachwork-light';
|
||||
import { createTravelDistance } from '@/scene/world/travel-distance';
|
||||
import {
|
||||
blendDaybreak,
|
||||
engineOffStarScale,
|
||||
createMutableChapterPalette,
|
||||
STORM_STAR_SCALE,
|
||||
STORM_TINT,
|
||||
@@ -34,6 +36,8 @@ import {
|
||||
import { createMaintenanceWindow } from '@/scene/world/maintenance-window';
|
||||
import { createHeadlights } from '@/scene/world/headlights';
|
||||
import { maintenanceProgress } from '@/journey/maintenance-progress';
|
||||
import { dawnStep, type DawnStep } from '@/journey/dawn';
|
||||
import { dawnLightUniforms } from '@/scene/world/dawn-light';
|
||||
import { isTestFault, recordTestFaultEvent } from '@/testing/fault-hooks';
|
||||
|
||||
declare const __PORTFOLIO_TEST_BUILD__: boolean;
|
||||
@@ -161,6 +165,10 @@ export async function createProceduralSceneGeneration(
|
||||
|| (typeof matchMedia === 'function' && matchMedia('(pointer: coarse)').matches)
|
||||
? 'lite'
|
||||
: 'full';
|
||||
// END OF SHIFT: the low tier and touch keep the palette, the sun lift and
|
||||
// the star drain (uniform writes); the warm rims and the bloom change are
|
||||
// high/medium fine-pointer only.
|
||||
const dawnRims = maintenanceTier === 'full';
|
||||
scene.add(
|
||||
maintenance.group,
|
||||
atmosphere.group,
|
||||
@@ -218,6 +226,7 @@ export async function createProceduralSceneGeneration(
|
||||
let interludeOn = false;
|
||||
let riseUntil = 0;
|
||||
let gantryState = '';
|
||||
let dawnState: DawnStep | '' = '';
|
||||
|
||||
const resize = (): void => {
|
||||
const nextWidth = Math.max(1, canvas.clientWidth || canvas.width || 1);
|
||||
@@ -342,14 +351,20 @@ export async function createProceduralSceneGeneration(
|
||||
targetPalette.starVisibility *= 1 - (1 - STORM_STAR_SCALE) * service.storm;
|
||||
}
|
||||
districts.setServiceState(service.dim, service.relight);
|
||||
// Engine off: parked at the destination the sky drops about 10%, more
|
||||
// stars come out, and the drive winds down to a stop.
|
||||
// END OF SHIFT: parked at the destination, the night ends. One scalar
|
||||
// drives it all; leaving rewinds it as fast as the outro returns.
|
||||
const dawn = easeInOutCubic(outroProgress);
|
||||
blendDaybreak(targetPalette, THREE.MathUtils.smoothstep(dawn, 0.15, 0.95));
|
||||
// Engine off: parked at the destination the sky drops about 10%, the
|
||||
// stars come out (then drain as the dawn rises), and the drive winds
|
||||
// down to a stop.
|
||||
const engineOff = THREE.MathUtils.smoothstep(outroProgress, 0.12, 0.7);
|
||||
if (engineOff > 0) {
|
||||
targetPalette.sky.lerp(ENGINE_OFF_NIGHT, 0.1 * engineOff);
|
||||
targetPalette.fog.lerp(ENGINE_OFF_NIGHT, 0.1 * engineOff);
|
||||
targetPalette.starVisibility *= 1 + 0.8 * engineOff;
|
||||
targetPalette.starVisibility *= engineOffStarScale(engineOff, dawn);
|
||||
}
|
||||
dawnLightUniforms.uDawnLight.value = dawnRims ? dawn : 0;
|
||||
dampPalette(currentPalette, targetPalette, deltaSeconds);
|
||||
const driveDistance = travelDistance.advance(
|
||||
deltaSeconds * (1 - engineOff),
|
||||
@@ -394,7 +409,7 @@ export async function createProceduralSceneGeneration(
|
||||
);
|
||||
atmosphericTime += deltaSeconds;
|
||||
const elapsedSeconds = atmosphericTime;
|
||||
horizonAir.update(currentPalette, elapsedSeconds);
|
||||
horizonAir.update(currentPalette, elapsedSeconds, dawn);
|
||||
skyline.update(currentPalette, elapsedSeconds);
|
||||
traffic.update(
|
||||
deltaSeconds,
|
||||
@@ -407,6 +422,7 @@ export async function createProceduralSceneGeneration(
|
||||
elapsedSeconds,
|
||||
Math.min(1, response.bloomEnergy + beat * 0.35),
|
||||
snapshot.arrived,
|
||||
dawn,
|
||||
);
|
||||
car.update(
|
||||
visualSpeed,
|
||||
@@ -437,6 +453,7 @@ export async function createProceduralSceneGeneration(
|
||||
currentPalette,
|
||||
atmosphericTime,
|
||||
overdrive,
|
||||
dawn,
|
||||
);
|
||||
background.copy(currentPalette.sky);
|
||||
scene.fog.color.copy(currentPalette.fog);
|
||||
@@ -644,6 +661,12 @@ export async function createProceduralSceneGeneration(
|
||||
riseUntil = 0;
|
||||
delete document.documentElement.dataset.interlude;
|
||||
}
|
||||
// END OF SHIFT: CSS keys the credit and the letterbox tint off this.
|
||||
const nextDawnState = dawnStep(dawn);
|
||||
if (nextDawnState !== dawnState) {
|
||||
dawnState = nextDawnState;
|
||||
document.documentElement.dataset.dawn = nextDawnState;
|
||||
}
|
||||
if (TEST_BUILD && snapshot.sign !== null) {
|
||||
const presentation = sign.inspect(camera, width, height);
|
||||
if (presentation !== null) {
|
||||
@@ -663,13 +686,14 @@ export async function createProceduralSceneGeneration(
|
||||
}
|
||||
}
|
||||
if (postProcessor) {
|
||||
postProcessor.setDynamics(response.bloomEnergy);
|
||||
postProcessor.setDynamics(response.bloomEnergy, dawnRims ? dawn : 0);
|
||||
postProcessor.setLens({
|
||||
time: elapsedSeconds,
|
||||
letterbox: 0.115 * (1 - THREE.MathUtils.smoothstep(introProgress, 0.5, 1)),
|
||||
energy: overdrive,
|
||||
rain: service.rain,
|
||||
rainTime: elapsedSeconds,
|
||||
dawn,
|
||||
});
|
||||
postProcessor.render(scene, camera);
|
||||
} else {
|
||||
@@ -683,6 +707,8 @@ export async function createProceduralSceneGeneration(
|
||||
delete document.documentElement.dataset.gantry;
|
||||
delete document.documentElement.dataset.interlude;
|
||||
delete document.documentElement.dataset.interludeArmed;
|
||||
delete document.documentElement.dataset.dawn;
|
||||
dawnLightUniforms.uDawnLight.value = 0;
|
||||
// Quality changes reuse the canvas context. Leave texture upload flags at
|
||||
// defaults before the next renderer creates its empty array textures.
|
||||
const gl = renderer.getContext();
|
||||
@@ -694,7 +720,8 @@ export async function createProceduralSceneGeneration(
|
||||
}
|
||||
|
||||
const INTRO_SECONDS = 4.2;
|
||||
const OUTRO_SECONDS = 5.5;
|
||||
/** Long enough for the dawn to read: the sun clears the skyline near 3.8 s. */
|
||||
const OUTRO_SECONDS = 7.0;
|
||||
const OUTRO_RETURN_SECONDS = 1.6;
|
||||
const OUTRO_REACH = 0.62;
|
||||
const ENGINE_OFF_NIGHT = new THREE.Color(0x000000);
|
||||
|
||||
Reference in New Issue
Block a user