Log inGet started
World

Cold Start

Branchmain
Commitcfc095f0fc

README.md

preseed/tides/light.module — THE FARJAN, LIGHT

Part 9's sun, fill, shadows, exposure and grade, under the SKY lane's weather.

What it owns

  • the scene's directional key and ambient fill, driven every frame from preseed.tides.state, and restored on the way out;
  • the key's occlusion, measured through the part's own cloud volume rather than scheduled;
  • the tonemap's exposure ramp and the bloom drive;
  • the print stage (preseed.shaders.tid_print) — chromatic aberration, the print black and the output dither;
  • the reflection probe's recapture schedule.

Three things that are not obvious

It drives the SCENE's sun and ambient, not lights of its own. /runtime/lighting resolves exactly one directional and one ambient, and in this scene they are the persistent sun and ambient entities. A part that spawns its own pair authors something nothing reads: measured mid-part with tid_sun at 3.0 and tid_ambient at 2.0 on their own entities, the resolved config was the scene sun at 0.12 and the scene ambient at 0.14. So this lane drives the scene's, remembers what it found, and puts it back in M.exit.

It WRITES the sun's direction, which reads backwards until you know why. src/engine/systems/sky.rs refuses to sync the sun onto the lighting config while a directional Light entity exists — the Light is "the sole authoritative writer" — so a Light left alone keeps its default straight-down direction while the visible disc goes wherever the sky puts it. State.sunDirection(t) is the vector toward the disc; a Light's direction is the way light TRAVELS, so the value written is its negation.

The key is measured, not scheduled. tid_key_probe.computeShader marches the SKY lane's own cloud volume from the ship toward the sun every frame and reports the mean transmittance over eight rays, and the key is keyOpen(t) * (1 - KEY_DEPTH * occlusion). State.light(t).keyOcclusion01 is only a FLOOR under that measurement, and it is zero until t = 24 — so for twenty-four seconds the key is the weather's answer and nothing else. The one exception is the slot at bar 22, which is authored and says so: the wedge of clear air is carved at the horizon, beyond 2.2 km, and the ship stands inside that radius under the rain veil, so the probe marching outward never sees the hole.

The order in P.update is load-bearing

CAMERA → LIGHT → SKY. LIGHT must come before SKY because it probes the volume SKY filled; SKY must be last because its raymarch builds its ray basis from the camera pose.

The print stage

Fx.grade matches its table against PP.PRESETS, which has no chromatic_aberration entry, so the brief's 0.0018 was read and dropped in silence. The shared fx.module is read by twelve other parts and is not this lane's to change, so the pass is added here from a tides-owned shader at priority 75 — after tonemap (60) and vignette (70), before the letterbox and fade (200). It also carries the part's print black and its dither, both driven per frame from printGrade(t): measured, round 1 put 21-57% of every frame at exactly (0,0,0) with the 25th percentile on zero in all twelve, which the brief forbids by name.

Budgets published for the FERRY lane

M.PRACTICAL_BUDGET = { points = 18, spots = 4, shadowCasting = 2 }. MAX_POINT_LIGHTS is 64 for the whole scene and over-cap lights are dropped silently rather than merged — and this part is not alone in it.