# Digital Rain — `digital-rain@1.0.0`

Columns of glowing code falling around the camera in layers of depth, with a message you can write in the rain. Loops perfectly.

Streams of invented glyphs falling in the dark, each with a white-hot head and a trail fading to black, seen from the middle of four concentric cylinders of them: the near glyphs are big and soft, the far ones small and fine, and the camera's slow sway slides the layers past each other. Cells flicker through an alphabet of 128 glyphs, quicker at the head of a column. Write a message of up to 24 letters and it appears in the finest layer as a dot-matrix of glowing glyphs that stays lit while the rain falls through it. Choose the colours (terminal green, cyan, amber or magenta), the message, how much rain, how fast it falls, how long the trails are, how big the glyphs, how many depth layers, how far the camera sways and how much the glyphs glow.

- Kind: background; status: published; digest sha256:2cfef652b3bcb188b0fe92327076adc132a2f4b134ebee266ee79a5e6db2d98b
- Role: Background (WebGL shader, full frame): a code-rain backdrop for tech, hacker, AI and title content, with an optional message.
- Implementation: three; entry `src/digital-rain.js`
- Files: https://aipixelwizard.com/registry/digital-rain/1.0.0/<path> (`LICENSE`, `asset.json`, `demo.js`, `index.html`, `src/digital-rain.js`)
- Manifest JSON: https://aipixelwizard.com/api/v1/visuals/digital-rain/versions/1.0.0
- Runnable demo: https://aipixelwizard.com/registry/digital-rain/1.0.0/index.html (open over http; it imports sibling packages by relative path)
- Dependencies (exact): `three@0.185.1` (source) — Renderer and the full-screen shader.; `apw-runtime@1.0.0` (demo) — Demo harness.

## Exports
- `createDigitalRain({ palette?, density?, fall?, trail?, size?, layers?, sway?, glow?, message?, seed? }) => { scene, camera, material, setSize(width, height), update(time, loopSeconds), dispose() }` — The whole rain as one full-screen shader: render its scene with its camera after setSize and update, 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.
- `PALETTES: { green, cyan, amber, magenta }` — The colour of the head of a column, of its body, and of the tail it fades to.
- `MAX_MESSAGE: 24` — The most letters a message can have.

## Parameters
- `palette` (select one of green | cyan | amber | magenta, default "green") — Colours
- `message` (text, default "Hello, world") — Message: Up to 24 letters, written in the finest layer of the rain.
- `density` (number 0.3–1, default 0.8) — Rain
- `fall` (integer 1–3, default 1) — Fall speed
- `trail` (number 0.5–1.6, default 1) — Trail length
- `size` (number 0.6–1.6, default 1) — Glyph size
- `layers` (integer 2–4, default 4) — Depth layers
- `sway` (number 0–1.5, default 1) — Camera sway
- `glow` (number 0–1.5, default 1) — Glow
- `seed` (integer 1–999, default 7) — Seed

## Composition
- Inputs: Time within the loop; the colours, message, amount of rain, speed, trails, glyph size, layers, sway and glow.
- Outputs: A full frame, drawn by one shader on a full-screen quad; the glyphs come from an atlas baked in JavaScript.
- Coordinates: The camera sits on the axis of four concentric cylinders (radii 1.2 to 4.6) of columns; the rays are intersected with them, so the glyphs curve gently towards the edges of the frame.
- Lighting: Self-lit: every glyph glows; the bloom adds the halation.
- Timing: update(time, loopSeconds) sets the loop phase; frames render in any order.
- Works with: kinetic-title, number-reveal
- No fonts and no image files: the alphabet is 128 invented glyphs (strokes between lattice points) baked into a signed-distance atlas, sharp or soft at any size.
- The message uses a 5 × 7 dot font, one cell of the finest layer to a dot.

## Output and loop
- 1080×1080, 30 fps, 12 s, procedural
- Seamless loop: yes — Each column's head falls a whole number of its own length per loop, so the rain wraps exactly; every cell changes glyph a whole number of times a loop (the glyph is picked from the cell and the count of changes modulo that whole number); the camera's sway is a sine of the 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, createDigitalRain({ message }) and createBloomPass(renderer, { width, height }); call rain.setSize(width, height), then each frame rain.update(time, loopSeconds) and bloom.render(rain.scene, rain.camera).

Existing project: Copy src/digital-rain.js; render rain.scene with rain.camera into a render target (or through the bloom pass) as the backdrop of your scene.

Reuse ideas:
- AI or tech title: Terminal green with the title as the message.
- Countdown or reveal: Amber terminal with a short message.
- Background for code and security explainers: Blue rain, no message.

## Limitations
- The glyphs are invented shapes, not real writing systems.
- The message sits in the finest layer, so it is small on screen unless it is short.

## 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/abstract-artistic/matrix-rain (MIT) and rebuilt for AI Pixel Wizard in October 2026 as an original shader: concentric cylinders of columns seen from their axis, signed-distance glyphs invented in code, a dot-matrix message, an exact loop and the frame/time contract.

