# Caustic Dance — `caustic-dance@1.0.0`

The bright, shifting net of light on the floor of a swimming pool, sliding over wobbling tiles. Loops perfectly.

The dancing net of sunlight on the floor of a pool: ripples on the surface bend the light into a lattice of thin bright lines that slides, splits and rejoins over blue tiles, which themselves wobble as the water bends them. Choose the water (turquoise, deep blue, lagoon or sunset), tiles on or off, the size of the net, its brightness and how thin its lines are, and how much the tiles wobble.

- Kind: background; status: published; digest sha256:dd2f4af5003ef53a99e7286ba14eea344dfb9c4c7f7e7a7e42200fae6bff3a97
- Role: Background (WebGL shader, full frame): a calm, bright water backdrop for summer, wellness, travel and title content.
- Implementation: three; entry `src/caustic-dance.js`
- Files: https://aipixelwizard.com/registry/caustic-dance/1.0.0/<path> (`LICENSE`, `asset.json`, `demo.js`, `index.html`, `src/caustic-dance.js`)
- Manifest JSON: https://aipixelwizard.com/api/v1/visuals/caustic-dance/versions/1.0.0
- Runnable demo: https://aipixelwizard.com/registry/caustic-dance/1.0.0/index.html (open over http; it imports sibling packages by relative path)
- Dependencies (exact): `three@0.185.1` (source) — Renderer, geometry and shader materials.; `apw-runtime@1.0.0` (demo) — Demo harness.

## Exports
- `createCausticPool({ water?, tiles?, scale?, brightness?, wobble?, sharpness? }) => { scene, camera, setSize(width, height), update(time, loopSeconds), dispose() }` — The pool floor and its light as one full-screen shader; render its scene with its camera, ideally through createBloomPass.
- `createBloomPass(renderer, { width, height, glow?, exposure?, grain? }) => { render(scene, camera, output?), dispose() }` — A small bloom with filmic tone mapping.
- `WATERS: { turquoise, deep, lagoon, sunset }` — Water tints (sRGB hex).

## Parameters
- `water` (select one of turquoise | deep | lagoon | sunset, default "turquoise") — Water
- `tiles` (boolean, default true) — Tiles
- `scale` (number 0.5–2, default 1) — Net size
- `brightness` (number 0.4–1.8, default 1) — Brightness
- `sharpness` (number 4–14, default 11) — Line sharpness: Higher makes thinner lines.
- `wobble` (number 0–2, default 1) — Tile wobble

## Composition
- Inputs: Time within the loop; the water, tiles, net size, brightness, line sharpness and tile wobble.
- Outputs: A full frame, drawn by one shader on a full-screen quad.
- Coordinates: Square-ish tiles about 1/7 of the frame high, seen from straight above.
- Lighting: Self-lit: the water's colour for the floor, the light's colour added where the caustic lines are; the bloom adds the glare.
- Timing: update(time, loopSeconds) sets the loop phase; frames render in any order.
- Works with: kinetic-title, number-reveal
- The caustic is five rounds of warping the point by folded sines and summing 1/distance, two layers at different scales; its time factors are integers so it repeats exactly.

## Output and loop
- 1080×1080, 30 fps, 12 s, procedural
- Seamless loop: yes — Every layer of the light and the wobble of the tiles are folded sines whose frequencies are whole numbers of cycles per loop, so the last frame meets the first.
- Verified 2026-10-06 in Chrome 154.0.8037.97 headless on Linux 7.0.0-38-generic (x64), Node 22.14.0 (WebGL 2 via SwiftShader (software)); deterministic: yes; loop check: Frame 0 vs end state (progress 1): mean |Δ| 0.0000, max |Δ| 0 of 255.

## Use it
New project: Create a WebGLRenderer, createCausticPool() and createBloomPass(renderer, { width, height }); call pool.setSize(width, height), then each frame pool.update(time, loopSeconds) and bloom.render(pool.scene, pool.camera).

Existing project: Copy src/caustic-dance.js; render pool.scene with pool.camera into a render target (or through the bloom pass) as a backdrop.

Reuse ideas:
- Summer or travel background: Turquoise pool tiles.
- Spa or wellness loop: Lagoon, no tiles.
- Evening title: Sunset water.

## Limitations
- The pattern is a stylised formula, not a ray-traced caustic: it does not respond to an actual surface.
- The floor is flat and seen from straight above.

## License
MIT. Copyright (c) 2026 AI Pixel Wizard. Released under the MIT License. See LICENSE in this folder.

Provenance: Adapted from the owner's threejs-sketches/light-atmosphere/caustic-dance (MIT) and rebuilt for AI Pixel Wizard in October 2026 as an original shader: a folded-sine caustic with whole-cycle time factors, wobbling pool tiles and an exact loop.

