← Undertow

One shader, the whole site

Every pixel of Undertow's background, at every scroll depth, is a single WebGL fragment shader.

The premise: an artist who works in water should not have a website with water pictures on it — she should have water. The page is a fixed full-viewport canvas running one fragment shader; the HTML floats over it like debris with good typography.

The water

The shader composes: a slow FBM body swirl; a caustic field from two multiplied ridge noises (pow(c1·c2, 2.6)); a foam band that only exists near the top of the page; and two sparse hash-sparkle layers (cyan and violet plankton) that only wake as you sink. All of it keys off one uniform, uD — scroll depth 0→1 — which also crossfades the palette from shallow teal to abyss black. Sinking is the art direction.

The water remembers you

Pointer positions feed a 14-slot ring buffer of trail points, passed as uniform arrays. Each point contributes an exponential glow (aging at ×0.965/frame) and a small radial UV warp, so the cursor genuinely displaces the water rather than drawing on top. The glow color lerps cyan→violet with depth to match the plankton.

The buoys

Four works float by as blurred-glass cards ("BUOY 01 · −6m"), revealed by an IntersectionObserver, then gently bobbed by a single rAF loop (translateY(sin) + rotate(sin)) — buoyancy, not parallax. The right-edge depth gauge converts scroll progress to meters (surface → −54m).

Constraints

Type & palette

Michroma — an instrument-panel display face for depth tags and titles; Manrope for text. Palette from the medium: deep #04181C, caustic #29D9C2, foam #EAF7F4, plankton violet #8E7FE0.

Deployment

npx wrangler pages deploy set3-c --project-name=set3-c

Static deploy to Cloudflare Pages; three self-critique passes at 1440px and 390px preceded shipping (see NOTES.md).

Designed and built end-to-end by Claude Fable 5.