{
  "schemaVersion": 1,
  "id": "sand-hourglass",
  "version": "1.0.0",
  "status": "published",
  "kind": "background",
  "title": "A Desert in an Hourglass",
  "summary": "Falling grains build a miniature dune country inside a brass hourglass: a sun and three camels walk the ridge, then a warm wind unthreads the caravan back into sand. Loops.",
  "description": "A brass-framed hourglass on a black-and-gold sand table. As the grains fall they pile into dunes in the lower bulb and a sun rises above them; three camels walk the ridge in a caravan. Then a warm wind lifts the grains, the caravan unthreads back into sand, and the sand returns to the upper bulb, so the 8 seconds loop. Individual grains, dune hatching and the camel silhouettes are all drawn in the shader. The film has no settings.",
  "role": "Shader film (three.js): Sand animation, a finished 8-second portrait film with no settings.",
  "collections": [
    "impossible-worlds",
    "hypnotic-loops"
  ],
  "tags": [
    "hourglass",
    "sand",
    "desert",
    "camels",
    "dunes",
    "time",
    "caravan",
    "sand art",
    "brass",
    "gold",
    "timer",
    "animal",
    "loop",
    "portrait film"
  ],
  "synonyms": [
    "sand art animation",
    "desert in an hourglass",
    "camel caravan",
    "sand timer",
    "sand clock",
    "time passing",
    "sand dunes loop"
  ],
  "useCases": [
    "A \"time\" or deadline theme for a countdown or a productivity video",
    "A travel or Middle-East tourism promo",
    "A looping sand-art backdrop for a title"
  ],
  "featured": null,
  "publishedAt": "2026-10-10",
  "implementation": {
    "target": "three",
    "runtime": "browser",
    "language": "javascript",
    "module": "esm",
    "entry": "src/sand-hourglass.js",
    "exports": [
      {
        "name": "createSandHourglass",
        "signature": "createSandHourglass() => { scene, camera, setSize(width, height), update(time), dispose() }",
        "description": "The film as one full-screen shader; render its scene with its camera straight to the canvas."
      }
    ],
    "reusable": [
      "src/sand-hourglass.js"
    ],
    "demo": "demo.js",
    "harness": "index.html"
  },
  "dependencies": [
    {
      "id": "three",
      "version": "0.185.1",
      "reason": "Renderer and a full-screen shader material."
    },
    {
      "id": "apw-runtime",
      "version": "1.0.0",
      "scope": "demo",
      "reason": "Demo harness."
    }
  ],
  "params": [],
  "presets": [],
  "output": {
    "width": 1080,
    "height": 1350,
    "fps": 30,
    "durationSeconds": 8,
    "posterSeconds": 5.5,
    "alpha": false,
    "motion": "procedural",
    "loop": {
      "seamless": true,
      "cycleSeconds": 8,
      "method": "Every part of the film is a function of the time modulo its length, and every motion completes whole cycles, so the last frame meets the first."
    },
    "seed": null
  },
  "composition": {
    "inputs": "The time in seconds, 0 to 8. The film has no other settings.",
    "outputs": "An opaque full-frame picture, already in display colours: render it straight to the canvas.",
    "coordinates": "Composed for a 4:5 portrait frame and measured by the frame height: in a wider frame the picture stays centred at full height and its background fills the sides; in a narrower one, such as 9:16, the sides are cropped.",
    "lighting": "A warm glow from the sun inside the glass, on a black sand-table ground.",
    "timing": "Grains fall and pile into dunes, a sun rises and three camels walk the ridge, then a wind unthreads the caravan back into sand.",
    "compatibleWith": [],
    "notes": [
      "The hourglass is a true twin-bulb silhouette with a brass frame.",
      "Grains falling and returning are individual points, not a texture.",
      "Every pixel is a function of the time alone, so frames can be rendered in any order."
    ]
  },
  "reuse": [
    "Time-passing b-roll: the hourglass runs once per loop, which suits a \"time is running out\" beat.",
    "Seamless loop: the sand returns to the top, so it repeats for any length.",
    "Travel promo: the caravan on the dune ridge holds from about 3 s to 6 s."
  ],
  "integration": {
    "newProject": "Create a WebGLRenderer on a canvas (no antialiasing), call createSandHourglass() once and film.setSize(width, height); then for each frame call film.update(timeInSeconds) and renderer.render(film.scene, film.camera).",
    "existingProject": "Copy src/sand-hourglass.js, which needs only three. Render film.scene with film.camera into your own canvas or render target; the output is opaque and already in display colours, so use no tone mapping or colour conversion."
  },
  "performance": {
    "notes": "One full-screen fragment shader. About 13 ms a frame at 1080 by 1350 on an integrated Intel GPU (Iris Xe), and about 3 s a frame with software WebGL.",
    "limits": "Plays at 30 frames a second at full size on an integrated GPU."
  },
  "limitations": [
    "The film is finished: it has no settings. To change colours or timing, edit the shader.",
    "It is composed for a 4:5 portrait frame.",
    "Its length is fixed at 8 seconds; repeat the loop to fill a longer clip."
  ],
  "license": {
    "spdx": "MIT",
    "notice": "Copyright (c) 2026 AI Pixel Wizard. Released under the MIT License. See LICENSE in this folder.",
    "thirdParty": []
  },
  "provenance": "From the owner's collection Twenty Impossible Worlds: the original GLSL ES 3.00 shader of the film “A Desert in an Hourglass”, created with ChatGPT / Codex and used as published, wrapped for AI Pixel Wizard as a three.js full-screen shader in October 2026. The collection's synthesised soundtrack is not part of this ingredient.",
  "changelog": [
    {
      "version": "1.0.0",
      "date": "2026-10-10",
      "notes": "Initial release."
    }
  ]
}
