# Campfire — `campfire@1.0.0`

A campfire at night in a ring of stones: a flickering flame, glowing logs, rising embers and smoke, trees and stars at the edge of the light. Loops perfectly.

Logs leaning together, stacked, or burnt down to a bed of coals, in a ring of stones, with cracks glowing on the bark; a roaring turbulent flame that lights the logs, stones and ground and flickers, throwing soft shadows; embers rising and cooling, smoke drifting up lit from below, trunks and a treeline at the edge of the light and a sky full of stars. Choose the fire (leaning logs, stacked logs or embers), the height of the flame, its colour (a wood fire, green-and-violet driftwood or deep red), the wind, the embers, the smoke, the trees, the moonlight and how far the camera sways.

- Kind: background; status: published; digest sha256:9a200dfd11c14d8698e350c5472419ae67382c1cc86f9c7579771c886012d252
- Role: Background (WebGL shader, full frame): a warm, calming night scene for storytelling, wellness, travel and cosy content.
- Implementation: three; entry `src/campfire.js`
- Files: https://aipixelwizard.com/registry/campfire/1.0.0/<path> (`LICENSE`, `asset.json`, `demo.js`, `index.html`, `src/campfire.js`)
- Manifest JSON: https://aipixelwizard.com/api/v1/visuals/campfire/versions/1.0.0
- Runnable demo: https://aipixelwizard.com/registry/campfire/1.0.0/index.html (open over http; it imports sibling packages by relative path)
- Dependencies (exact): `three@0.185.1` (source) — Renderer, the full-screen shader, the embers and the bloom targets.; `apw-runtime@1.0.0` (demo) — Demo harness.

## Exports
- `createCampfire({ layout?, size?, flame?, wind?, embers?, smoke?, trees?, moon?, sway?, seed?, aspect? }) => { scene, camera, material, pit, setSize(width, height), update(time, loopSeconds), dispose() }` — The whole scene: one full-screen shader (fire, logs, stones, ground, trees, sky) and the embers as points. 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.
- `planFire({ layout?, seed? }) => { logs, stones, trees, flame }` — The fire pit: the logs as segments, the ring of stones, the trees round the edge of the light, and how big the flame is for the layout.
- `FLAMES: { natural, driftwood, ember }` — Flame colours: its heart, its body, and its edge.
- `LAYOUTS: ['teepee', 'stacked', 'embers']` — The ways the logs can be laid.

## Parameters
- `layout` (select one of teepee | stacked | embers, default "teepee") — Fire
- `size` (number 0.7–1.4, default 1) — Flame height
- `flame` (select one of natural | driftwood | ember, default "natural") — Flame colour
- `wind` (number -0.6–0.6, default 0.2) — Wind
- `embers` (number 0–1.5, default 1) — Embers
- `smoke` (number 0–1.5, default 0.8) — Smoke
- `trees` (boolean, default true) — Trees
- `moon` (number 0.4–1.8, default 1) — Moonlight
- `sway` (number 0–1.5, default 1) — Camera sway
- `seed` (integer 1–999, default 5) — Seed

## Composition
- Inputs: Time within the loop; the layout of the fire, flame height and colour, wind, embers, smoke, trees, moonlight and camera sway.
- Outputs: A full frame: one ray-tracing shader on a full-screen quad, and the embers as instanced points drawn additively over it.
- Coordinates: World units of about a metre: the fire at the origin, the ring of stones 1.5 away, the camera 5.4 back and 1.1 up looking slightly down at the fire; trees stand 6 to 14 away.
- Lighting: The fire is the light: a point light at the heart of the flame that flickers, with inverse-square falloff, soft shadows from the logs and stones, and a dim bluish moonlight; the flame, the glowing cracks and the coals are emissive.
- Timing: update(time, loopSeconds) sets the loop phase; every part is a closed-form function of it, so frames render in any order.
- Works with: kinetic-title, number-reveal
- Logs are capsules and stones flattened spheres in a signed-distance field that is sphere-traced only where a ray comes near the pit; the ground is a plane and the trunks are upright cylinders.
- The flame is a volume (a teardrop thinning with height, torn into tongues by three octaves of scrolling noise) marched in 26 steps; the smoke is a wider, dimmer column marched in 12.

## Output and loop
- 1080×1080, 30 fps, 12 s, procedural
- Seamless loop: yes — The noise that makes the flame and the smoke scrolls a whole number of its texture's periods per loop (every octave's offset is a whole number of periods); every flicker of the light is a sum of sines with whole numbers of cycles; each ember is born and spent inside the loop, timed with a modulo; the camera sways in 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, createCampfire({ aspect }) and createBloomPass(renderer, { width, height }); call fire.setSize(width, height), then each frame fire.update(time, loopSeconds) and bloom.render(fire.scene, fire.camera).

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

Reuse ideas:
- Cosy storytelling or sleep video: Campfire in the woods, slow.
- Camping or travel intro: Stacked logs, windy, behind a title.
- Fantasy or beach scene: Driftwood fire on the shore.

## Limitations
- The flame is a smooth volume, not a fluid simulation: it flickers and tears but does not curl round the logs.
- The ground and trees are dark and simple: the forest is a handful of trunks and a silhouette.

## 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/nature-organic/campfire (with fire-weather/campfire-embers, MIT) and rebuilt for AI Pixel Wizard in October 2026 as an original ray-traced scene: a signed-distance fire pit with glowing cracks and soft shadows, a volumetric flame and smoke from scrolling noise, closed-form embers, an exact loop and the frame/time contract.

