# Hourglass — `hourglass@1.0.0`

A glass-and-brass hourglass: the sand runs, the glass flips, the sand runs again. Loops perfectly.

A classic sand glass floating in a dark studio: a glass double-bulb between two turned metal plates on three slender posts. A thin stream of sand runs through the neck, the upper pile sinking into a funnel while the lower one builds a cone at the angle of repose; when it has all run through the glass turns over, the sand slumping from the cone into a funnel on its new top, and it runs again. Choose the sand (any colour), the metal of the frame (brass, copper, chrome or black), a tint in the glass, and how much of the loop is spent turning the glass over.

- Kind: object; status: published; digest sha256:06c46e25249807efe6eff43986bfa0eb450c45ac2130dfc9c1bb40edd64b308a
- Role: Hero object (Three.js 3D): the classic symbol of time running out, for countdowns, deadlines and reflective content.
- Implementation: three; entry `src/hourglass.js`
- Files: https://aipixelwizard.com/registry/hourglass/1.0.0/<path> (`LICENSE`, `asset.json`, `demo.js`, `index.html`, `src/hourglass.js`)
- Manifest JSON: https://aipixelwizard.com/api/v1/visuals/hourglass/versions/1.0.0
- Runnable demo: https://aipixelwizard.com/registry/hourglass/1.0.0/index.html (open over http; it imports sibling packages by relative path)
- Dependencies (exact): `three@0.185.1` (source) — Renderer, physical glass and metal, and the sand's ray-marching shader.; `chrome-material@1.1.0` (demo) — Studio environment light, backdrop, floor and contact shadow.; `apw-runtime@1.0.0` (demo) — Demo harness.

## Exports
- `createHourglass({ sand?, finish?, tint?, origin?, seed? }) => { group, half, uniforms, update(time, loopSeconds, { flip? }), dispose() }` — The hourglass as a THREE.Group (1 unit = 10 cm), hung at origin. update(time, loopSeconds) runs the sand and then turns the glass over; the whole thing repeats exactly. Set uniforms.uKey to your key light's direction.
- `FINISHES: { brass, copper, chrome, black }` — Finishes for the plates and posts.

## Parameters
- `sand` (color, default "#e3b86a") — Sand
- `finish` (select one of brass | copper | chrome | black, default "brass") — Frame
- `tint` (color, default "#ffffff") — Glass tint
- `flip` (number 0.1–0.35, default 0.2) — Time spent turning over: The share of the loop that the glass spends turning, 0.1 to 0.35.
- `background` (color, default "#10131b") — Backdrop
- `seed` (integer 1–999, default 3) — Seed: Changes the grain of the sand.

## Composition
- Inputs: Time within the loop; the sand colour, frame finish, glass tint and the share of the loop spent turning over.
- Outputs: A THREE.Group: plates, posts, glass and the sand volume, centred on the origin (or origin option).
- Coordinates: 1 unit = 10 cm. The glass is 2.6 tall inside two plates, 3.0 overall, and 1.1 across at its widest.
- Lighting: Physical glass and metal: needs scene.environment. The sand is lit in its own shader by a key light (set uniforms.uKey to the real light's direction) and a sky fill.
- Timing: update(time, loopSeconds) is a pure function of time; frames render in any order.
- Works with: chrome-material, orbit-camera, kinetic-title
- The sand volume is opaque on purpose: three.js transmission refracts only opaque objects, so the glass can show it.
- To make a countdown, set the loop to your countdown's length and spend the flip share at its end.

## Output and loop
- 1080×1080, 30 fps, 16 s, procedural
- Seamless loop: yes — The sand runs, then the glass turns over by exactly half a turn. The glass, plates, posts and sand are all symmetric under that half turn (the grain is defined in each bulb's own frame), 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: Set scene.environment (createStudioEnvironment from Chrome Material works), add createHourglass({ origin }).group and a light, set uniforms.uKey, and call update(time, loopSeconds) each frame.

Existing project: Copy src/hourglass.js. Add the group to your scene (scale it to suit), set uniforms.uKey to your key light, and call update(seconds, loopSeconds) every frame.

Reuse ideas:
- Deadline: Golden sand, brass frame, with a bold 'Time is running out' over the top.
- Timer sting: White sand in chrome, a 10-second loop, then your logo.
- Documentary: Slate sand in copper, slow, behind a voice-over about time.

## Limitations
- The sand is a smooth volume with a grain texture, not simulated grains: the stream is a thin steady column.
- The glass turns about its centre in mid-air; it never rests on a surface.

## 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/objects-scenes/hourglass-sand (and webgpu-hourglass-flow) (MIT), rebuilt for AI Pixel Wizard in October 2026: a ray-marched sand volume with a cone and a funnel at the angle of repose, a stream, a modelled glass and turned frame that are symmetric under a half turn so the flip loops exactly, and the frame/time contract.

