Skip to content

sardistic/waves

Repository files navigation

waves

A procedural, audio- and mouse-reactive WebGL recreation of a hand-drawn black-and-white Adult Swim wave/rain bumper — rendered live in a single fragment shader.

▶ Live demo

hero

What it is

The whole scene is one WebGL2 fragment shader (index.html, no build step): rolling forward-leaning swells, a stipple-boiled sand shore, a spray halo, falling rain, and a stack of crest-parallel foam strands — all reacting to mouse movement and to live microphone or an uploaded audio file.

The look isn't guessed. It was measured from the reference footage. Rather than synthesizing foam procedurally (Voronoi cells and sine lines were both tried and rejected), the hand-drawn foam is extracted from the source frames, rectified into wave-space, converted to signed-distance fields, and stacked into a texture atlas (foam_atlas.png) that the shader samples and morphs through over time.

reference vs render

Pipeline

The reference video was analysed frame-by-frame; the shader was built from the numbers, not from eyeballing. The scripts that produced the assets:

Script Role
extract_waves.py Pull the wave region out of each reference frame.
make_atlas.py Rectify hand-drawn foam into wave-space, convert to SDF, stack into foam_atlas.png.
study.py / study2.py / study3.py Fit the measured constants (waterline slosh, foam spacing/thickness, stipple density, rain streaks).
compare.py Stack a headless render under the reference frame and diff coverage metrics.
check_atlas.py Sanity-check the generated atlas slices.

Key measured facts baked into the shader:

  • Foam = level sets of a warped log-depth field, spacing ~0.042 uv at the crest widening ~4× by mid-depth; thickness tapers crest → deep.
  • Waterline = a standing slosh, mean ~0.27 uv, ±0.07, period ~3 s.
  • Sand = uniform-noise stipple re-randomized ~8×/s (the "boil").
  • Rain = peak brightness ~0.17, streaks ~0.055H, over ~20% of columns.
  • Audio = bass-onset detection surges wave height and breaking activity on the beat.

Run locally

The demo is fully static — index.html only needs foam_atlas.png beside it, so any static file server works:

npm install     # optional: pulls express for the bundled server
npm start        # serves on http://localhost:3000

Or just open index.html over any static host (e.g. python -m http.server).

Controls

  • Move the mouse — perturbs the sea.
  • T — toggle the tuner panel (12 live parameters; config is saved to localStorage).
  • H — hide/show the UI.
  • mic / audio file — drive the animation with live or uploaded audio.

Regenerating the assets

The heavy source assets (the reference *.mp4, the extracted frames/ and wave_assets/, and the study/ screenshots) are gitignored to keep the repo lean. Point the scripts at your own source video and re-run extract_waves.pymake_atlas.py to rebuild foam_atlas.png.

License

MIT — see LICENSE.

About

animated webgl waves that are aesthetic and respond to mouse/audio

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors