# Rainy Window — `rain-window@1.0.0`

Rain running down a misted window at night, the city lights blurred into soft bokeh behind it. Loops perfectly.

Looking out through a wet window: the street beyond is out of focus, its lamps, car lights and neon melted into round bokeh, while the water on the glass is sharp. Small beads land and merge away; larger drops slide down in fits and starts, clearing a trail through the condensation that slowly mists over again, and every drop holds a tiny upside-down picture of the lights. Choose the view (city night, neon street, golden hour or a grey morning with trees), how hard it rains, how misted the glass is, the drop size and the blur, and optionally write a word in the mist as if with a fingertip.

- Kind: background; status: published; digest sha256:0e7071d4372d2a38b16e5a717fb51a798cbae15274c4e6fd3f5fa9089d713469
- Role: Background (WebGL, full frame): a moody, cosy rain-on-glass loop for lofi, music and storytelling.
- Implementation: three; entry `src/rain-window.js`
- Files: https://aipixelwizard.com/registry/rain-window/1.0.0/<path> (`LICENSE`, `asset.json`, `demo.js`, `index.html`, `src/rain-window.js`)
- Manifest JSON: https://aipixelwizard.com/api/v1/visuals/rain-window/versions/1.0.0
- Runnable demo: https://aipixelwizard.com/registry/rain-window/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 glass, bokeh and backdrop shaders.; `neon-sign@1.0.0` (demo) — Its tube alphabet for the word written in the mist.; `apw-runtime@1.0.0` (demo) — Demo harness.

## Exports
- `createRainOnGlass(renderer, { width, height, rain?, fog?, size?, blur?, refraction?, highlights?, mist?, wipe?, seed?, exposure?, grain? }) => { render({ background, time, loopSeconds, output? }), dispose() }` — Rain, mist and bokeh over any background texture (a photo, a video or another scene), drawn to the canvas or a render target.
- `createRainScene(renderer, { scene?, width, height, seed? }) => { texture, render(time, loopSeconds), dispose() }` — The four built-in views behind the glass, in linear light with real highlights, so they bloom into bokeh.
- `RAIN_SCENES: ['city', 'neon', 'dusk', 'morning']` — Names of the built-in views.

## Parameters
- `scene` (select one of city | neon | dusk | morning, default "city") — View
- `rain` (number 0–1, default 0.6) — Rain
- `fog` (number 0–1, default 0.5) — Mist on the glass
- `dropSize` (number 0.6–1.6, default 1) — Drop size
- `blur` (number 0.4–1.6, default 1) — Background blur
- `message` (text, default "") — Written in the mist: A short word or two, as if written with a fingertip. Leave empty for none.
- `seed` (integer 1–999, default 1) — Seed: Changes where the drops are and how they run.

## Composition
- Inputs: Time within the loop and a background texture (the built-in views, or any picture, video or render target).
- Outputs: A full frame: the background out of focus behind wet, misted glass.
- Coordinates: Screen space; drop sizes are fractions of the frame height, so the look holds at any resolution.
- Lighting: Self-contained: the backdrops are in linear light, and the drops refract the in-focus picture and catch a highlight from the room.
- Timing: Everything is a pure function of time within the loop; frames render in any order.
- Works with: kinetic-title, gradient-background, page-turn
- The written word is treated as private: not stored in shared packs unless you choose to include it.
- Over your own footage, pass a texture as background and set highlights to about 0.5 so bright spots bloom into bokeh.
- The finger-written lettering comes from Neon Sign's tube alphabet.

## Output and loop
- 1080×1080, 30 fps, 10 s, procedural
- Seamless loop: yes — Every drop lands, slides and is absorbed a whole number of times per loop, trails mist over by age since the last pass, and the traffic and signals behind repeat with 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, createRainScene and createRainOnGlass at the canvas size, then each frame call backdrop.render(time, loop) and glass.render({ background: backdrop.texture, time, loopSeconds: loop }).

Existing project: Copy src/rain-window.js. Render your scene (or play a video) into a texture and pass it as the background; draw the glass as the last full-screen pass.

Reuse ideas:
- Lofi stream: City at night, rain 0.5, behind a small music player or a quote.
- Music video: Neon street with the camera's own footage on a screen in frame.
- Short film: Grey morning with a heart in the mist as a quiet opening shot.

## Limitations
- Drops follow designed paths rather than a fluid simulation: they never merge with each other on the way down.
- The written word uses Neon Sign's alphabet: Latin letters with accents, digits and common punctuation.

## 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/liquid-fluid/webgpu-rain-window (MIT), rebuilt for AI Pixel Wizard in October 2026 in WebGL as a frame-exact loop: designed bead and sliding-drop paths instead of a simulation, real round-aperture bokeh, refracting drops, mist that clears and returns, four backdrops, and the frame/time contract.

