Skip to the content.

Preset SDK — add a visual mode

Two ways in:

Everything below applies to both.

The two laws

  1. Determinism — nothing wall-clock may touch a pixel. Seed randomness from u.time or a hash of position; never Math.random/Date.now.
  2. WYSIWYG — a preset is a pure function of (features, time, params). That purity is why the live preview and the exported file are the same render.

PresetDef

export const myMode: PresetDef = {
  id: "my-mode", // stable — projects reference it
  name: "My Mode",
  description: "One user-facing line.",
  styles: [
    // 5–7 curated looks; first = defaults
    { id: "default", name: "Default", values: {} },
    { id: "ember", name: "Ember", values: { hue: 20, glow: 0.8 } },
  ],
  params: [
    // main knobs (schema -> auto UI)
    {
      key: "hue",
      label: "Hue",
      min: 0,
      max: 360,
      step: 1,
      default: 200,
      hint: "What turning this visibly does",
    },
  ],
  advanced: [/* every internal constant worth touching */],
  wgsl: /* wgsl */ `
fn preset(uv: vec2f) -> vec4f {
  // your fragment shader — uv is 0..1
  return vec4f(0.0, 0.0, 0.0, 1.0);
}`,
};

Params become WGSL accessors P_<key>(). A param with min:0, max:1, step:1 renders as a toggle. styles values are partial overrides — machine-check yours against the schema like themes.test.ts does.

Audio uniforms (u.)

Field Meaning
time Track time, seconds. THE animation clock.
drive Smoothed envelope of the user’s Sync source. Use this so the Sync panel matters.
driveBeat Onset pulse of the Sync source: 1 on a hit, exponential decay.
bpm, beatPhase, barPhase Beat grid: tempo, 0..1 within the beat, 0..1 within a 4-beat bar. 0 when no grid.
bass, mid, treble, voice Band energies 0..1.
kick, snare, hat Per-drum onset envelopes.
rms, energy Instant / slow (~0.8 s) loudness.
beatIntensity Legacy low-end beat pulse.
progress time/duration (0 in live input mode).
width Stereo width.
spin, pulse, detail, specSmooth Motion masters — multiply your rotation / beat-scale / element count by these.
aspect, binCount, waveCount, smoothBins, bgMode, bgColor Housekeeping.

WGSL helpers

Special paths: particles: { count } runs a built-in GPU compute simulation instead of your fragment (see particleFlow.ts); mesh3d: { grid } runs a depth-tested instanced 3D grid (see spectrumScape.ts).

Craft notes