{
  "schemaVersion": 1,
  "id": "fireworks",
  "version": "1.0.0",
  "status": "published",
  "kind": "background",
  "title": "Fireworks",
  "summary": "A fireworks show over a harbour at night: shells climb, burst into peonies, willows and rings, light the smoke and mirror in the water. Loops perfectly.",
  "description": "Rockets trailing sparks climb into a dark sky and burst into peonies, chrysanthemums, golden willows, rings, palms and crackling glitter. Every spark is white-hot when it is born, changes colour as it burns and cools to an ember, drawn as a trail that bends under gravity. The bursts flash the sky, light the smoke they leave and are mirrored in the water below a small harbour town, a city skyline or a ridge of pines. Choose the show (a mixed finale, peonies, willows or rings), the colours, how many shells, how wide they open, how long the trails are, how much smoke, the scenery and the mirror.",
  "role": "Background / effect (WebGL, full frame): a celebratory night scene for new year, festival, event and holiday content.",
  "collections": [
    "backgrounds",
    "hypnotic-loops"
  ],
  "tags": [
    "fireworks",
    "night sky",
    "celebration",
    "new year",
    "festival",
    "sparks",
    "smoke",
    "reflection",
    "harbour",
    "city skyline",
    "loop",
    "background"
  ],
  "synonyms": [
    "firework display",
    "fireworks show",
    "pyrotechnics",
    "new year fireworks",
    "fourth of july",
    "firecrackers",
    "sparklers",
    "night celebration"
  ],
  "useCases": [
    "A new year, festival or holiday intro and countdown backdrop",
    "An event, wedding or concert celebration scene",
    "A finale for a story, a game or a product launch video"
  ],
  "featured": null,
  "publishedAt": "2026-10-06",
  "implementation": {
    "target": "three",
    "runtime": "browser",
    "language": "javascript",
    "module": "esm",
    "entry": "src/fireworks.js",
    "exports": [
      {
        "name": "createFireworks",
        "signature": "createFireworks({ show?, palette?, shells?, size?, trails?, smoke?, scenery?, reflection?, seed?, aspect?, loopSeconds? }) => { scene, camera, plan, setSize(width, height), update(time, loopSeconds), dispose() }",
        "description": "The whole show: a backdrop and instanced spark ribbons in one scene. Render it with its camera, ideally through createBloomPass."
      },
      {
        "name": "createBloomPass",
        "signature": "createBloomPass(renderer, { width, height, glow?, exposure?, grain? }) => { render(scene, camera, output?), dispose() }",
        "description": "A small bloom with filmic tone mapping and a fixed grain: draws a scene to the canvas with its glow."
      },
      {
        "name": "planShow",
        "signature": "planShow({ show?, palette?, shells?, size?, trails?, seed?, aspect?, loopSeconds? }) => [{ kind, launch, rise, x, y, size, sparks, colours }]",
        "description": "The schedule of a show: when each shell launches, where it bursts, what kind it is and its colours."
      },
      {
        "name": "PALETTES",
        "signature": "PALETTES: { festival, gold, ice, sunset }",
        "description": "Colour pairs: what a burst starts as and what it turns to."
      },
      {
        "name": "SHOWS",
        "signature": "SHOWS: { finale, peonies, willows, rings }",
        "description": "The programmes: the kinds of shell, in order."
      },
      {
        "name": "KINDS",
        "signature": "KINDS: ['peony', 'chrysanthemum', 'willow', 'ring', 'palm', 'crackle']",
        "description": "The kinds of shell the shader draws."
      }
    ],
    "reusable": [
      "src/fireworks.js"
    ],
    "demo": "demo.js",
    "harness": "index.html"
  },
  "dependencies": [
    {
      "id": "three",
      "version": "0.185.1",
      "reason": "Renderer, instanced ribbons and the bloom targets."
    },
    {
      "id": "apw-runtime",
      "version": "1.0.0",
      "scope": "demo",
      "reason": "Demo harness."
    }
  ],
  "params": [
    {
      "key": "show",
      "label": "Show",
      "type": "select",
      "default": "finale",
      "options": [
        {
          "value": "finale",
          "label": "Finale (a mix)"
        },
        {
          "value": "peonies",
          "label": "Peonies and crackle"
        },
        {
          "value": "willows",
          "label": "Golden willows"
        },
        {
          "value": "rings",
          "label": "Rings and palms"
        }
      ]
    },
    {
      "key": "palette",
      "label": "Colours",
      "type": "select",
      "default": "festival",
      "options": [
        {
          "value": "festival",
          "label": "Festival"
        },
        {
          "value": "gold",
          "label": "Gold and white"
        },
        {
          "value": "ice",
          "label": "Ice blue"
        },
        {
          "value": "sunset",
          "label": "Sunset"
        }
      ]
    },
    {
      "key": "shells",
      "label": "Shells per loop",
      "type": "integer",
      "min": 3,
      "max": 12,
      "step": 1,
      "default": 7
    },
    {
      "key": "size",
      "label": "Burst size",
      "type": "number",
      "min": 0.7,
      "max": 1.4,
      "step": 0.05,
      "default": 1
    },
    {
      "key": "trails",
      "label": "Trail length",
      "type": "number",
      "min": 0.5,
      "max": 1.6,
      "step": 0.05,
      "default": 1
    },
    {
      "key": "smoke",
      "label": "Smoke",
      "type": "number",
      "min": 0,
      "max": 1.5,
      "step": 0.05,
      "default": 0.8
    },
    {
      "key": "scenery",
      "label": "Scenery",
      "type": "select",
      "default": "harbour",
      "options": [
        {
          "value": "harbour",
          "label": "Harbour town"
        },
        {
          "value": "city",
          "label": "City skyline"
        },
        {
          "value": "hills",
          "label": "Hills and pines"
        }
      ]
    },
    {
      "key": "reflection",
      "label": "Mirror in the water",
      "type": "number",
      "min": 0,
      "max": 1,
      "step": 0.05,
      "default": 1
    },
    {
      "key": "seed",
      "label": "Seed",
      "help": "Changes where and in which order the shells burst, their colours and the shore.",
      "type": "integer",
      "min": 1,
      "max": 999,
      "step": 1,
      "default": 7
    }
  ],
  "presets": [
    {
      "id": "default",
      "label": "Finale over the harbour",
      "params": {}
    },
    {
      "id": "willows",
      "label": "Golden willows over the pines",
      "params": {
        "show": "willows",
        "palette": "gold",
        "scenery": "hills",
        "shells": 6,
        "smoke": 1,
        "seed": 12
      }
    },
    {
      "id": "city",
      "label": "New year over the city",
      "params": {
        "show": "peonies",
        "scenery": "city",
        "shells": 9,
        "size": 1.1,
        "seed": 21
      }
    },
    {
      "id": "ice",
      "label": "Ice rings",
      "params": {
        "show": "rings",
        "palette": "ice",
        "scenery": "hills",
        "shells": 6,
        "seed": 31
      }
    }
  ],
  "output": {
    "width": 1080,
    "height": 1080,
    "fps": 30,
    "durationSeconds": 12,
    "posterSeconds": 8.5,
    "alpha": false,
    "motion": "procedural",
    "loop": {
      "seamless": true,
      "cycleSeconds": 12,
      "method": "Every shell is scheduled round the loop and measures its own time with a modulo, so each is spent before its next launch comes round; the smoke drifts on a circle of the noise and the water ripples, the stars twinkle and the lights blink in whole cycles."
    },
    "seed": {
      "param": "seed",
      "behavior": "Seed picks where and in which order the shells burst, which colours they take and the shape of the shore: same seed, same show."
    }
  },
  "composition": {
    "inputs": "Time within the loop; the show, colours, shell count, burst size, trails, smoke, scenery, mirror.",
    "outputs": "A full frame: the night, the shore and the water drawn by one shader, and every spark as an instanced ribbon drawn additively over it.",
    "coordinates": "Orthographic: x from -aspect to aspect, y from -1 to 1; the water line sits at y = -0.36 and bursts open between 0.04 and 0.52.",
    "lighting": "Self-lit: each burst flashes and lights the sky and its smoke in its own colour; the bloom adds the glow.",
    "timing": "update(time, loopSeconds) sets the time; each spark is a closed-form function of it, so frames render in any order.",
    "compatibleWith": [
      "kinetic-title",
      "number-reveal"
    ],
    "notes": [
      "The sparks are not simulated: position follows x(t) = x0 + a t / k + (v0 - a / k)(1 - e^(-k t)) / k for gravity a and air drag k.",
      "Rockets shed their own falling sparks; bursts of every kind differ in drag, weight, life and trail so willows droop and peonies stay round."
    ]
  },
  "reuse": [
    "New year countdown: Finale over the harbour behind a number reveal.",
    "Wedding or concert opener: Golden willows with a slow title.",
    "Festival video: New year over the city, shells set to 9."
  ],
  "integration": {
    "newProject": "Create a WebGLRenderer, createFireworks({ aspect }) and createBloomPass(renderer, { width, height }); each frame call show.update(time, loopSeconds) then bloom.render(show.scene, show.camera).",
    "existingProject": "Copy src/fireworks.js; render show.scene with show.camera into a render target, or through the bloom pass, as an overlay of your scene."
  },
  "performance": {
    "notes": "About 3,000 spark ribbons (each a strip of seven pieces) positioned in the vertex shader, one full-screen backdrop and a small bloom: no per-frame JavaScript work beyond setting the time.",
    "limits": "More than 12 shells need a larger array in the shader."
  },
  "limitations": [
    "The sky, the town and the sparks are flat: the bursts are drawn face-on, not as spheres in depth.",
    "No sound."
  ],
  "license": {
    "spdx": "MIT",
    "notice": "Copyright (c) 2026 AI Pixel Wizard. Released under the MIT License. See LICENSE in this folder.",
    "thirdParty": [
      {
        "name": "three.js",
        "version": "0.185.1",
        "license": "MIT",
        "url": "https://github.com/mrdoob/three.js"
      }
    ]
  },
  "provenance": "Adapted from the owner's threejs-sketches/objects-scenes/webgpu-fireworks (MIT) and rebuilt for AI Pixel Wizard in October 2026 as an original closed-form show: shells scheduled round an exact loop, six kinds of burst, white-hot sparks that change colour and cool to embers, lit smoke, a mirrored harbour and three kinds of shore.",
  "changelog": [
    {
      "version": "1.0.0",
      "date": "2026-10-05",
      "notes": "Initial release."
    }
  ]
}
