Files
djaudiovisualizer/src/effects.js
T
lucianoandClaude Fable 5 7e745743c5 Ten more interactive camera families: bubbles, balloons, particle mirror, cloth, light painting, touch fluid, electric silhouette, swarm, tile wall, firewall
interactive.js becomes a multi-mode engine sharing camera, motion grid,
gradient/centroid tracking and the mouse fallback. New renderers: point/line
sprites (mirror/swarm/cloth/pops) and a ping-pong trail FBO (painting).
fluid.js gains a 'touch' emitter mode fed by motion splats from the camera.
Mirror mode reforms the custom SVG/image if loaded, else a DJ LUZA wordmark.
UNPACK_ALIGNMENT set to 1 for non-multiple-of-4 single-channel uploads.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 23:26:34 +02:00

151 lines
7.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Effect catalog generator. Combines 16 shader families × color palettes ×
// style variants to produce hundreds of named presets. Shared by both windows.
// Wrapped in an IIFE so its locals don't leak into the shared global scope
// (control.js also defines an EFFECTS reference).
(function () {
const FAMILIES = [
{ name: 'Julia', scale: 1.35 },
{ name: 'Mandelbrot', scale: 1.1 },
{ name: 'Plasma', scale: 1.0 },
{ name: 'Vortice', scale: 1.0 },
{ name: 'Onde', scale: 1.0 },
{ name: 'Cellule', scale: 1.0 },
{ name: 'Iperspazio', scale: 1.0 },
{ name: 'Tunnel', scale: 1.0 },
{ name: 'Moiré', scale: 1.0 },
{ name: 'Truchet', scale: 1.0 },
{ name: 'Gyroide', scale: 1.0 },
{ name: 'Esagoni', scale: 1.0 },
{ name: 'Reticolo', scale: 1.0 },
{ name: 'Nuvole', scale: 1.0 },
{ name: 'Spirale', scale: 1.0 },
{ name: 'Cristalli', scale: 1.0 },
{ name: 'Ballerini', scale: 1.0, bgDark: true },
{ name: 'Ballerino', scale: 1.0, bgDark: true },
{ name: 'Sagome', scale: 1.0, bgDark: true },
{ name: 'SVG/Immagine', scale: 1.0, bgDark: true },
{ name: 'VU Barre', scale: 1.0, bgDark: true },
{ name: 'VU Analogico', scale: 1.0, bgDark: true },
{ name: 'VU Stereo', scale: 1.0, bgDark: true },
{ name: 'Waveform', scale: 1.0, bgDark: true },
{ name: 'Waveform Radiale', scale: 1.0, bgDark: true },
{ name: 'Tri-Banda', scale: 1.0, bgDark: true },
{ name: 'Reattivo Bassi', scale: 1.0, bgDark: true },
{ name: 'Reattivo Medi', scale: 1.0, bgDark: true },
{ name: 'Reattivo Alti', scale: 1.0, bgDark: true },
// GPU fluid sim families (fluid.js), not the uber-shader; fluidMode picks
// the emitter choreography over the same solver.
{ name: 'Fluido', scale: 1.0, fluid: true },
{ name: 'Fluido Fuoco', scale: 1.0, fluid: true, fluidMode: 'fire' },
{ name: 'Fluido Anello', scale: 1.0, fluid: true, fluidMode: 'ring' },
{ name: 'Fluido Vortici', scale: 1.0, fluid: true, fluidMode: 'vortex' },
{ name: 'Fluido Onda', scale: 1.0, fluid: true, fluidMode: 'wave' },
// Scenic RGB families (uber-shader indices 34+, fieldRGB path): full-colour
// scenes tinted by the palette. Append-only: existing preset indices are
// stored in saved scenes/pads and must not shift.
{ name: 'Cielo', scale: 1.0 },
{ name: 'Aurora', scale: 1.0 },
{ name: 'Mare', scale: 1.0 },
{ name: 'Montagne', scale: 1.0 },
{ name: 'Galassia', scale: 1.0 },
{ name: 'Solidi 3D', scale: 1.0 },
{ name: 'Griglia Neon', scale: 1.0 },
{ name: 'Tunnel Neon', scale: 1.0 },
{ name: 'Tempesta Plasma', scale: 1.0 },
{ name: 'Supernova', scale: 1.0 },
// Camera-interactive families (interactive.js): webcam motion drives the
// scene (interMode picks the behaviour). Excluded from Auto VJ (turning the
// camera on must stay a deliberate user choice). Append-only.
{ name: 'Interattivo Palle', scale: 1.0, interactive: true },
{ name: 'Interattivo Bolle', scale: 1.0, interactive: true, interMode: 'bubbles' },
{ name: 'Interattivo Palloncini', scale: 1.0, interactive: true, interMode: 'balloons' },
{ name: 'Interattivo Specchio', scale: 1.0, interactive: true, interMode: 'mirror' },
{ name: 'Interattivo Tessuto', scale: 1.0, interactive: true, interMode: 'cloth' },
{ name: 'Interattivo Pittura', scale: 1.0, interactive: true, interMode: 'paint' },
{ name: 'Interattivo Fluido', scale: 1.0, interactive: true, interMode: 'fluid' },
{ name: 'Interattivo Silhouette', scale: 1.0, interactive: true, interMode: 'silhouette' },
{ name: 'Interattivo Sciame', scale: 1.0, interactive: true, interMode: 'swarm' },
{ name: 'Interattivo Piastrelle', scale: 1.0, interactive: true, interMode: 'tiles' },
{ name: 'Interattivo Firewall', scale: 1.0, interactive: true, interMode: 'firewall' }
];
// Palettes: low colour (a) -> high colour (b), plus optional hue-cycle/sat.
const PALETTES = [
{ name: 'Neon', a: [0.05, 0.0, 0.2], b: [0.2, 1.0, 1.0], cycle: 0.02 },
{ name: 'Tramonto', a: [0.15, 0.0, 0.1], b: [1.0, 0.65, 0.1], cycle: 0.01 },
{ name: 'Oceano', a: [0.0, 0.05, 0.18], b: [0.1, 0.8, 1.0], cycle: 0.01 },
{ name: 'Foresta', a: [0.0, 0.08, 0.03], b: [0.5, 1.0, 0.2], cycle: 0.01 },
{ name: 'Lava', a: [0.1, 0.0, 0.0], b: [1.0, 0.3, 0.0], cycle: 0.015 },
{ name: 'Ghiaccio', a: [0.02, 0.05, 0.1], b: [0.7, 0.9, 1.0], cycle: 0.005 },
{ name: 'Viola', a: [0.08, 0.0, 0.15], b: [0.8, 0.2, 1.0], cycle: 0.02 },
{ name: 'Oro', a: [0.1, 0.06, 0.0], b: [1.0, 0.85, 0.3], cycle: 0.008 },
{ name: 'Arcobaleno', a: [0.6, 0.1, 0.8], b: [0.1, 0.9, 0.3], cycle: 0.12 },
{ name: 'Monocromo', a: [0.0, 0.0, 0.0], b: [1.0, 1.0, 1.0], cycle: 0.0, sat: 0.0 },
{ name: 'Acido', a: [0.1, 0.2, 0.0], b: [0.7, 1.0, 0.0], cycle: 0.03 },
{ name: 'Pastello', a: [0.4, 0.3, 0.5], b: [1.0, 0.8, 0.9], cycle: 0.02, sat: 0.7 },
{ name: 'Cyberpunk', a: [0.2, 0.0, 0.3], b: [1.0, 0.1, 0.6], cycle: 0.04 },
{ name: 'Infrarosso', a: [0.0, 0.0, 0.1], b: [1.0, 0.0, 0.2], cycle: 0.02 },
{ name: 'Menta', a: [0.0, 0.1, 0.08], b: [0.4, 1.0, 0.8], cycle: 0.01 },
{ name: 'Sabbia', a: [0.15, 0.1, 0.05], b: [0.95, 0.8, 0.55], cycle: 0.006 },
{ name: 'Semaforo', a: [0.0, 1.0, 0.2], b: [1.0, 0.0, 0.0], cycle: 0.0 } // green -> red (VU)
];
// Style variants: how the universal modifiers are set.
const VARIANTS = [
{ suffix: '', sym: 0, warp: 0.0, speed: 1.0, rotSpeed: 0.0, contrast: 0.8 },
{ suffix: ' · Kaleido', sym: 6, warp: 0.0, speed: 1.0, rotSpeed: 0.04, contrast: 0.9 },
{ suffix: ' · Specchio8', sym: 8, warp: 0.1, speed: 1.0, rotSpeed: 0.02, contrast: 0.9 },
{ suffix: ' · Warp', sym: 0, warp: 0.5, speed: 1.4, rotSpeed: 0.0, contrast: 0.8 },
{ suffix: ' · Turbo', sym: 0, warp: 0.2, speed: 2.2, rotSpeed: 0.06, contrast: 1.0 },
{ suffix: ' · Mirror12', sym: 12, warp: 0.0, speed: 0.8, rotSpeed: 0.03, contrast: 0.95 }
];
function makeEffect(fi, pi, vi) {
const fam = FAMILIES[fi], pal = PALETTES[pi], v = VARIANTS[vi];
return {
name: `${fam.name} · ${pal.name}${v.suffix}`,
familyName: fam.name,
paletteName: pal.name,
family: fi,
scale: fam.scale,
rot: 0,
rotSpeed: v.rotSpeed,
sym: v.sym,
hueBase: 0,
hueCycle: pal.cycle,
sat: pal.sat !== undefined ? pal.sat : 1.0,
contrast: v.contrast,
invert: 0,
warp: v.warp,
audioMix: 1.0,
speed: v.speed,
colorA: pal.a,
colorB: pal.b,
bgDark: fam.bgDark ? 1 : 0,
// Always present (0/1 and a mode string) so Object.assign merges in
// setEffect can't leave a stale flag behind when switching presets.
isFluid: fam.fluid ? 1 : 0,
fluidMode: fam.fluidMode || 'ink',
isInteractive: fam.interactive ? 1 : 0,
interactiveMode: fam.interMode || 'balls'
};
}
// Build the full catalog (16 × 16 × 6 = 1536 presets).
const EFFECTS = [];
for (let fi = 0; fi < FAMILIES.length; fi++)
for (let pi = 0; pi < PALETTES.length; pi++)
for (let vi = 0; vi < VARIANTS.length; vi++)
EFFECTS.push(makeEffect(fi, pi, vi));
window.EFFECTS = {
list: EFFECTS,
families: FAMILIES.map(f => f.name),
palettes: PALETTES.map(p => p.name),
count: EFFECTS.length,
defaults: () => makeEffect(2, 0, 0) // Plasma · Neon
};
})();