01 · The Brief, As Received
Orders from the director
Six sites were commissioned in one wave, each with a fixed identity and exactly one technique to push past comfortable. MONSUN drew the storm.
- ConceptThe northeast monsoon as an instrument — tens of thousands of GPU raindrops over a dark strait, and you hold the wind.
- PaletteAbyssal #05090c · rain silver #9fb4c0 · lightning #eaf6ff · instrument jade #3fbf8f
- TypeAnton, condensed display · IBM Plex Sans, text · IBM Plex Mono for anything that reads like an instrument
- SignatureGPU storm — rain as Three.js line segments with a velocity-streak shader; lightning relights the whole scene; the cursor is wind shear.
- VoiceWeather-service laconic. The data does the poetry.
- Prove40,000 things moving at 60 fps in one browser tab.
02 · The Signature Technique
Rain that never touches the CPU
The obvious build updates 40,000 positions in JavaScript every frame and dies on a phone. This one never does: each drop's position is a function of time, computed in the vertex shader. The CPU uploads the geometry once, then only moves a clock forward. Wrap-around fall, wind lean, cursor shear, and the streak itself all happen on the GPU.
// index.html — rain vertex shader (excerpt, verbatim) float s = uSpd*(0.7+aSp*0.8); float y = mod(position.y*uH - uT*s, uH); // eternal fall, no reset logic float fall = uH - y; float x = position.x*uSpan - uSpan*0.5 + uWind*fall*0.12; vec2 d = vec2(x,y) - uCur.xy; // cursor in rain-space float sh = exp(-dot(d,d)/110.0) * uCur.z; // wind shear, gaussian falloff x += sh; vec3 vel = normalize(vec3(uWind*2.2 + sh*3.0, -s, 0.0)); vec3 p = vec3(x,y,z) + vel*(aTip-1.0)*(1.1+aSp*1.4); // tail follows velocity → streak
Each drop is two vertices. The tail vertex is displaced backward along the velocity vector, so faster drops draw longer streaks — and when wind bends the fall, the streaks bend with it.
Lightning is the same discipline: one flash scalar drives the rain tint, the sea shader's reflection stripe, the scene fog color, and a DOM radial glow — one number, four surfaces, so the whole strait agrees about the light.
03 · Critique Log
What the passes found
- Pass 1 — legibility vs. the storm Found: hero sub-text washed out against bright rain streaks; HUD unreadable on mobile where it covered a third of the viewport; counters started at 0 on screen. Fixed: text-shadow plates per constitution law 12, HUD rebuilt as a bottom instrument bar under 760px, counters begin mid-animation. Upgrade added: hold the pointer ≥450 ms and release — a charged triple-fork strike marches across the strait.
- Pass 2 — rhythm and dead zones Found: section plates all left-aligned made the scroll monotonous; the bulletin log reflowed as teletype lines arrived; marquee text duplicated oddly on 390px. Fixed: alternating plate alignment, reserved line-height for the teletype, marquee re-spaced. Upgrade added: a vertical marginalia rail with live station clock (UTC+8) and coordinates, watching from the left edge.
- Pass 3 — the cold read Found: the marginalia rail's vertical text overran the viewport and folded into a broken double column; the hero kicker broke a coordinate in half at 390px; the footer page-weight stat was a hardcoded guess. Fixed: rail text shortened and set no-wrap, coordinates made unbreakable, weight measured from the shipped file. Upgrade added: squall fronts — every twenty-odd seconds a gust shoves all forty thousand drops sideways, and the telemetry calls it GUST in jade.
- Pass 4 — instrument honesty Found: page copy ghosted faintly through the mobile instrument bar's translucent plate; the sign-off paragraph ended on a two-word widow line. Fixed: the bar went fully opaque, the line breaks were made unbreakable. Upgrade added: RANGE — every strike now reports its distance and bearing in the telemetry, computed from where the bolt actually lands in the scene.