Demo UI ======= The Noisemaker Shader Demo is an interactive browser-based playground for exploring GPU shader effects. It provides real-time rendering with live parameter controls, a DSL code editor, and support for both WebGL 2 and WebGPU backends. A hosted demo can be viewed at https://noisemaker.app/demo/shaders/ What the Demo Does ------------------ The shader demo provides: - **Effect browser** with categorized presets (synth, filter, nm, etc.) - **Live parameter controls** generated automatically from effect definitions - **DSL code editor** for composing effect chains programmatically - **Backend switching** between GLSL (WebGL 2) and WGSL (WebGPU) - **Bidirectional sync** between controls and DSL text Quick Start ----------- **Running locally:** .. code-block:: bash # Start a local server cd /path/to/noisemaker npx http-server -p 8000 # Open in browser open http://localhost:8000/demo/shaders/ **Embedding in your project:** .. code-block:: html
Components ---------- CanvasRenderer ~~~~~~~~~~~~~~ The core rendering engine that manages the GPU pipeline: .. code-block:: javascript import { CanvasRenderer } from './shaders/src/renderer/canvas.js'; const renderer = new CanvasRenderer({ canvas: HTMLCanvasElement, // Target canvas width: 1024, // Render resolution height: 1024, basePath: '../../shaders', // Path to shader assets preferWebGPU: false, // Use WebGPU if available useBundles: false, // Use pre-built effect bundles bundlePath: '../../dist/effects', onFPS: (fps) => { }, // FPS callback onError: (err) => { } // Error callback }); // Load effect manifest, fetch the bundles you'll use, then compile await renderer.loadManifest(); await renderer.loadEffect('synth/noise'); await renderer.compile('search synth\nnoise().write(o0)\nrender(o0)'); renderer.start(); // Control playback renderer.pause(); renderer.resume(); renderer.stop(); UIController ~~~~~~~~~~~~ Manages the demo UI — effect selection, controls, DSL editing: .. code-block:: javascript import { UIController } from './lib/demo-ui.js'; const ui = new UIController(renderer, { effectSelect: document.getElementById('effect-select'), dslEditor: document.getElementById('dsl-editor'), controlsContainer: document.getElementById('controls'), statusEl: document.getElementById('status'), fpsCounterEl: document.getElementById('fps'), onControlChange: () => { /* handle control changes */ }, onRequestRecompile: () => { /* handle recompile requests */ } }); // Load an effect await ui.loadEffect('synth/noise'); // Get current DSL const dsl = ui.getDsl(); DSL Language ~~~~~~~~~~~~ Effects are composed using a chainable DSL: .. code-block:: text // Basic noise search synth noise().write(o0) render(o0) // Chained effects search synth, filter noise(octaves: 4, scale: 2.0) .posterize(levels: 8) .bloom(radius: 0.5) .write(o0) render(o0) // Multiple surfaces search synth, mixer noise().write(o0) noise(seed: 42).write(o1) blend(tex: read(o1), amount: 0.5).write(o0) render(o0) See :doc:`language` for full DSL specification. Bundling for Distribution ------------------------- For production deployments, shader effects can be bundled into standalone JavaScript modules. Building Bundles ~~~~~~~~~~~~~~~~ .. code-block:: bash npm run bundle:shaders This produces: - ``dist/shaders/noisemaker-shaders-core.esm.js`` — Core runtime + UI (ESM) - ``dist/shaders/noisemaker-shaders-core.min.js`` — Minified IIFE variant - ``dist/effects/{namespace}/{effect}.js`` — Per-effect mini-bundles Using Bundles ~~~~~~~~~~~~~ .. code-block:: javascript import { CanvasRenderer, UIController } from './noisemaker-shaders-core.esm.js'; const renderer = new CanvasRenderer({ canvas, width: 512, height: 512, useBundles: true, bundlePath: './effects' }); await renderer.loadManifest(); await renderer.loadEffect('synth/noise'); await renderer.compile('search synth\nnoise().write(o0)\nrender(o0)'); renderer.start(); URL Parameters ~~~~~~~~~~~~~~ The demo supports URL parameters for deep linking: - ``?effect=synth/noise`` — Load specific effect - ``?backend=webgpu`` — Select rendering backend - ``?bundles=1`` — Use pre-built effect bundles Pluggable Controls ------------------ The UI system is designed to be **pluggable** — downstream projects can substitute custom web components for the default HTML elements. Overview ~~~~~~~~ The ``UIController`` class manages all UI interactions for the shader demo: - Effect selection and loading - DSL editing and parsing - Dynamic control generation from effect parameters - Bidirectional sync between controls and DSL text The control system allows downstream projects to substitute custom web components (like ``