Drift Aquarium · Field notes
How MEDUSA
was built.
One moon jelly in dark water, rendered live in the browser. It swims by contracting its bell on a real muscle-pulse cycle, trails sixteen tentacles and four oral arms on verlet soft-body physics, and leans toward the brightest thing it can find — your cursor.
01The concept
Drift Aquarium is a fiction: an aquarium that keeps one animal per darkened room. Tank 07 holds a single Aurelia aurita. The page has exactly one job — to make you sit still and watch a creature move as if it were alive, because the way it moves is alive: nothing is on a loop. The bell is a motor, the arms are a solved cloth, and the steering is a reflex answering your pointer.
02Palette
Four colours, argued from a dark tank. The cyan is bioluminescence — reserved for the bell rim, the pulse flash and marks, never for small body text, so contrast never drops below 4.5:1.
Text tokens: body #C6D0E2, labels #B9B1EF — both cleared for legibility over the dark water rather than set in the accent cyan.
03Type
MEDUSA
Syne · 800 · display & headings
A single moon jelly, kept in dark water.
Inter · 400–600 · body & labels
Syne carries the personality: its wide, slightly liquid caps read like a specimen label blown up to poster scale, and the wordmark's final A is dropped to weight 600 with a hairline stroke — a small typographic swim against the solid mass of the other letters. Inter does the quiet work: the field notes, the tank specs, the tiny uppercase labels, all held legible over moving water.
04Techniques
- three.js 0.160A single WebGL scene, capped at DPR 2, resized to the viewport and paused when the tab is hidden. If the context fails, a CSS/SVG jelly takes its place — no blank canvas.
- Bell shaderA parametric dome whose vertices are deformed in the vertex shader from two attributes (ring & angle); normals are computed analytically by finite-differencing the same function, so the fresnel stays correct as the bell squeezes. The fragment adds a thin cyan rim and the four-leaf gonad clover glowing through the mesoglea.
- Verlet armsSixteen marginal tentacles and four oral arms, each a chain of point masses integrated with verlet and relaxed against fixed segment lengths. Each root is pinned to the live, pulsing bell margin — so a lunge flicks them and a glide lets them catch up. One draw call per group.
- PhototaxisThe cursor is unprojected to a point in the water; the bell's aim is slerped toward it. Idle for a few seconds and the target blends into a slow figure-eight wander, so the animal never stops drifting.
The signature — a bell that is a motor. A pulse lasts under three seconds and is deliberately lopsided: a fast contraction, then a slow elastic recovery. Each frame samples that curve to get one number, the contraction, which does two jobs at once. It is handed to the vertex shader to physically squeeze the bell — margin pulling in and up, dome elongating — and its rising rate is turned into thrust, applied along the bell's apex axis only while the curve climbs. So the jelly surges on the power-stroke, coasts through the recovery, and surges again — a soft jet you can read in its motion. The same rate briefly brightens the rim, a bioluminescent flash timed to the beat. The physics and the picture come from one shared value; there is no faked animation loop anywhere in it.
05The three passes
Pass 1 — Craft
- The first render read as an opaque cyan ring: the fresnel was cyan-dominated and the body alpha too low, so only the silhouette showed. Warmed the deep tone toward violet, tightened the cyan to a thin additive rim, and raised the milky base alpha so the whole dome reads as translucent mesoglea.
- The jelly wandered half off-screen. Tightened the swim bounds and cut the wander amplitude so it stays framed, rising through the wordmark.
- Fixed the wordmark scale — "MEDUSA" is one unbreakable word and overflowed 375px at the old size; re-tuned the clamp so it fits every width.
- Killed a stray %0 NaN in the plankton drift that was throwing a console warning on every frame.
Pass 2 — Depth
- Added the bioluminescent flash: the rim brightens on each power-stroke, so the light itself pulses in time with the swim — the second-read reward once you notice the beat.
- Added a cursor-proximity glow: the four-leaf gonad clover brightens as the jelly closes on your pointer, so the animal visibly notices the light it is chasing.
- Varied the marginal tentacle lengths and segment counts — alternating long/short with a little jitter — to break the uniform picket-fence look into something that hangs like real strands.
Pass 3 — Hardening
- 375 / 768 / 1440 verified in headless Chrome: no horizontal overflow, nav and wordmark fully inside the viewport box.
- Reduced-motion path renders a settled static jelly — the verlet arms are relaxed over 160 steps, one frame is drawn, and no rAF loop starts. The animation warms up the same way so the first visible frame is never a straight-line burst.
- Confirmed the loop pauses on document.hidden and clamps its delta on resume, DPR is capped at 2, and focus-visible rings are present on every link.
- Chanel rule: collapsed the twin background caustic blobs into a single quiet wash behind the text.
Designed & built by Sapience Analytics — part of the Generative Assets collection. Every visual on the site is procedural: no photographs, no video, just WebGL, canvas maths and CSS.