Sunlight bent by a rippling pool surface draws a living net of light on the tiles.
The water surface is a spectrum of gravity-capillary waves on a 256 by 128 FFT grid, each mode turning at its own frequency from the dispersion relation, so a touch spreads as a train of rings with short ripples racing ahead of the long ones. Every frame more than 100,000 sun rays are refracted through the local surface normal with Snell's law, carried to the floor 1.4 m below and splatted into a light buffer, where converging rays pile up into the bright caustic network; floating leaves block their rays and cast shadows. The view from above sees the tiles through the same slopes and adds a Fresnel reflection of the sky with sun glitter. Below the surface, a fisheye camera looks up into Snell's window: the whole sky squeezed into a 97 degree cone, ringed by the treeline and surrounded by a totally reflecting mirror of the caustic floor.
Try it. Touch or drag across the water to send out rings of ripples. Use the buttons, or click the view and press V to dive under for Snell's window, W to change the wind and R for a rain shower.
Paste this into Claude Code, Codex or any coding agent to get a simple version running, then take it wherever you like.
Build an animated swimming pool floor with sunlight caustics, the bright wobbling net of light you see on the bottom of a sunny pool, using JavaScript and the HTML canvas element. Put everything in a single index.html file with no libraries or build step, so I can open it directly in a browser.
Start simple:
- Make a canvas that fills the window and stays sharp on high-DPI screens. Do the per-pixel work in a small offscreen canvas (about 320 by 200) and draw it scaled up.
- Model the water surface as a height field h(x, y): the sum of about a dozen sine waves with random directions, wavelengths and phases, each moving at its own speed. Also compute the slope (dh/dx, dh/dy) analytically.
- For every cell of a grid on the surface, send a sun ray straight down, bend it with Snell's law (n = 1.33) using the surface normal, and follow it to the floor about 1.5 m below. Add 1 to a light buffer at the pixel where it lands. Where rays bunch up you get bright lines; where they spread the floor goes dim. That is the whole trick.
- Paint the floor as pale tiles with thin grout lines and multiply it by the light buffer, then tint everything aqua so red fades with depth.
Once that works, make it beautiful:
- Splat each ray into the four nearest pixels with bilinear weights and give every ray a small random offset, then blend each frame with the last one so the light lines are smooth instead of speckled.
- Look at the floor through the waves: shift each floor lookup by a little of the surface slope so the tiles wobble.
- Let a click or drag drop ripples into the surface (expanding rings that fade) and watch the caustic net reorganize around them.
Explain the key ideas in short code comments. When you're done, tell me how to open it and suggest three directions I could take it next, such as floating leaves whose shadows come out of the same rays, a proper spectral (FFT) wave model, or an underwater view looking up into Snell's window.