REBUILD / storytelling.noomoagency.com
The surface is solved, not played back.
Two solvers run every frame and their normals are blended: a Navier-Stokes grid for the cursor’s wake, and a wave-equation ripple for the ring that travels out from it. Every constant below was read out of the site’s own bundle and scroll timeline — no value was measured off a screenshot.
Normal blend
Timeline
FluidSimulation — Navier-Stokes
| token | value | read from |
|---|---|---|
| targetPixels | 2^18 (2^16 mobile) | static targetPixels = _E() ? 2**16 : 2**18 |
| dye scale | 2x sim per axis | createRTs(e, t, i) with i = 2 |
| pressure iterations | 2 | for (let t = 0; t < qne; t++), qne = 2 |
| pressure decay | 0.99 | clearProgram.value = B1 = .99 |
| velocity dissipation | 0.99 | advection dissipation = Kne = .99 |
| density dissipation | 0.97 | advection dissipation = Yne = .97 |
| vorticity curl | 10 | vorticityProgram.curl = Jne = 10 |
| splat radius | 0.0015 → 0.001 | Fluid_epsSize.position.y |
| normal epsilon | 0.1 → 0.005 | Fluid_epsSize.position.x |
| pointer force gain | 1e4 | dx: (t - prevPointer.x) * 1e4 |
| pointer min travel | 1e-4 | distanceTo(prevPointer) > 1e-4 |
SimpleFluidSim — wave equation
| token | value | read from |
|---|---|---|
| simDamping | 0.98 | #define simDamping 0.98 |
| trailSize | 0.035 | #define trailSize 0.035 |
| trailPulseWidth | 0.02 | #define trailPulseWidth 0.02 |
| trailPulseFrequency | pi * 4 (2 Hz) | #define trailPulseFrequency pi * 4. |
| neighbour offset | 3.6 texels | vec3 e = vec3(3.6 * texelSize, 0.) |
| injection gain | 2 | ripple * 2. + (t + r + b + l) * 0.5 - prev.y |
| buffer scale | 0.5 | constructor(e = .5) |
| step / max substeps | 1/60 s · 5 | simDt = 1/60, const i = 5 |
Water — composite
| token | value | read from |
|---|---|---|
| type | 0.5 (fixed) | ke(dl.typeProvider, .5) — the .z track is never bound |
| emissionFactor | 5 → 1 | Water_emissionXWhitenessType.position.x |
| emissionWhiteness | 0 → 0.5 | Water_emissionXWhitenessType.position.y |
| opacity | 1 (x0.25 mobile) | Water_opacity.position.x, opacityMultiplier |
| color | 255,255,255 → 255,192,64 | Water_color.position |
| blueness | 0.02 | @G Water.blueness 0 0.1 0.02 |
| vignette | pow(16·uv.x·uv.y, 1.1) | uv = vUv(1-vUv)·0.99 + 0.005 |
| refraction | uv + normal.xz | vec2 uv = vScreenUv + normal.xz; |