# Thunderstorm — `thunderstorm@1.0.0`

A storm at night over the sea: forked lightning lighting the clouds, rain slanting through the flashes and a lighthouse beam turning in the dark. Loops perfectly.

Banks of cloud that glow from inside when lightning strikes, forked bolts that grow down in a stepped leader and flash in a bright return stroke with two flickering re-strikes, sheets of light in the cloud and crawling discharges across it, rain slanting through the light, a dark heaving sea that catches every flash in a column of glitter, and, on the coast, a striped lighthouse turning its beam through the rain (or, out at sea, a small ship riding the swell). Choose the scenery, how many flashes there are in the loop, how hard it rains, how heavy the cloud is, how bright the lightning is and its colour (cold white, violet, amber or green), and the wind.

- Kind: background; status: published; digest sha256:c4acf95552a8cf2d004ed3bb8912c08563b09e8ee365840cf5903ffa63baf202
- Role: Background (WebGL shader, full frame): a dramatic night storm for horror, thriller, weather and moody title content.
- Implementation: three; entry `src/thunderstorm.js`
- Files: https://aipixelwizard.com/registry/thunderstorm/1.0.0/<path> (`LICENSE`, `asset.json`, `demo.js`, `index.html`, `src/thunderstorm.js`)
- Manifest JSON: https://aipixelwizard.com/api/v1/visuals/thunderstorm/versions/1.0.0
- Runnable demo: https://aipixelwizard.com/registry/thunderstorm/1.0.0/index.html (open over http; it imports sibling packages by relative path)
- Dependencies (exact): `three@0.185.1` (source) — Renderer, instanced bolts and the bloom targets.; `apw-runtime@1.0.0` (demo) — Demo harness.

## Exports
- `createThunderstorm({ scenery?, strikes?, rain?, clouds?, brightness?, tint?, wind?, seed?, aspect?, loopSeconds? }) => { scene, camera, events, setSize(width, height), update(time, loopSeconds), dispose() }` — The whole storm: a backdrop of cloud, sea, coast and rain, and every bolt as instanced ribbons, in one scene. Render it 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: draws a scene to the canvas with its glow.
- `planStorm({ strikes?, seed?, loopSeconds?, scenery?, aspect? }) => [{ kind, t0, xTop, yTop, xG, yG, segments }]` — The schedule of the lightning: when each flash comes, where, what kind (ground strike, sheet, crawl) and the segments of its channel.
- `TINTS: { storm, violet, amber, green }` — The colours of the lightning.

## Parameters
- `scenery` (select one of lighthouse | sea, default "lighthouse") — Scenery
- `strikes` (integer 1–10, default 5) — Flashes per loop
- `rain` (number 0–1.6, default 1) — Rain
- `clouds` (number 0.7–1.4, default 1) — Heavy cloud
- `brightness` (number 0.5–1.6, default 1) — Lightning brightness
- `tint` (select one of storm | violet | amber | green, default "storm") — Lightning colour
- `wind` (number -0.6–0.6, default 0.25) — Wind: The slant of the rain: negative leans the other way.
- `seed` (integer 1–999, default 4) — Seed: Changes when and where the lightning strikes, the shape of its forks and the clouds.

## Composition
- Inputs: Time within the loop; the scenery, flashes per loop, rain, cloud, lightning brightness and colour, wind.
- Outputs: A full frame: the night, cloud, sea, coast and rain drawn by one shader, and every lightning channel as an instanced ribbon drawn additively over it.
- Coordinates: Orthographic: x from -aspect to aspect, y from -1 to 1; the horizon sits at y = -0.28 and the clouds fill the sky above it.
- Lighting: Self-lit: each flash lights the clouds, rain, sea and coast in the colour of the lightning by its distance to the channel; the beam of the lighthouse lights the rain and the cloud.
- Timing: update(time, loopSeconds) sets the time; each flash is a closed-form function of the seconds since it began, so frames render in any order.
- Works with: kinetic-title, number-reveal
- A strike is a stepped leader reaching the ground in 85 ms, a return stroke that fades in 70 ms and two more strokes at 0.24 s and 0.40 s, with a weak current flickering on to 0.7 s.
- The channels are generated once by midpoint displacement with branches and twigs; the cloud lightning crawls sideways inside the cloud.

## Output and loop
- 1080×1080, 30 fps, 12 s, procedural
- Seamless loop: yes — Every flash is scheduled round the loop and times itself with a modulo; the rain and the waves scroll through a texture that repeats a whole number of times a loop (every octave's multiplier along the scroll is a whole number); the clouds churn on circles of the noise and the beam and the ship turn and roll in whole cycles, 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, createThunderstorm({ aspect }) and createBloomPass(renderer, { width, height }); call storm.setSize(width, height), then each frame storm.update(time, loopSeconds) and bloom.render(storm.scene, storm.camera).

Existing project: Copy src/thunderstorm.js; render storm.scene with storm.camera into a render target (or through the bloom pass) as the backdrop or an overlay of your scene.

Reuse ideas:
- Thriller or horror opener: Storm over the lighthouse behind a slow title.
- Weather or news explainer: Distant storm, rain turned down.
- Sleep or ambience loop: Open-sea tempest with the lightning dimmed.

## Limitations
- The sea, the coast and the clouds are flat layers drawn from noise, not a 3D scene; the lighthouse and the ship are silhouettes.
- No thunder: the video has no sound.

## License
MIT. Copyright (c) 2026 AI Pixel Wizard. Released under the MIT License. See LICENSE in this folder.
- three.js 0.185.1: MIT (https://github.com/mrdoob/three.js)

Provenance: Adapted from the owner's threejs-sketches/fire-weather/lightning-storm (with webgpu-lightning-bolt, webgpu-thundercloud and webgpu-supercell-storm, MIT) and rebuilt for AI Pixel Wizard in October 2026 as an original scene: jagged forked channels with a stepped leader and re-strikes, clouds lit from within by each flash, scrolling rain, a heaving sea with glitter columns, a lighthouse with a turning beam, an exact loop and the frame/time contract.

