// Organic family: domain-warped plasma. The workhorse sustain scene — it holds // up for minutes because the warp keeps folding new structure into itself rather // than cycling. export const plasmaBloom = { name: 'Plasma Bloom', family: 'organic', kind: 'fragment', // Personality: see look/Personality.js. traits: ['camera', 'space', 'style'], params: { scale: { type: 'float', range: [0.8, 6], default: 2.4, uniform: 'u_scale', bias: 'density' }, warp: { type: 'float', range: [0, 3], default: 1.2, uniform: 'u_warp' }, speed: { type: 'float', range: [0.02, 0.5], default: 0.1, uniform: 'u_speed', bias: 'motion', rate: true }, bands: { type: 'float', range: [1, 10], default: 3.5, uniform: 'u_bands' }, softness:{ type: 'float', range: [0, 1], default: 0.5, uniform: 'u_softness' }, glow: { type: 'float', range: [0, 1.5], default: 0.4, uniform: 'u_glow', bias: 'energy' }, palette: { type: 'palette', count: 6 }, }, reactive: { warp: { feature: 'bandLow', amount: 0.35 }, glow: { feature: 'beat', amount: 0.35, response: 'spike' }, bands: { feature: 'centroid', amount: 0.2, response: 'smooth' }, }, shader: ` vec4 scene(vec2 uv, vec2 p) { float t = u_time * u_speed + u_seed; p = sigCamera(p); // Two rounds of domain warping. One looks like noise; two looks organic. vec2 q = vec2(fbm(p * u_scale + t, 4), fbm(p * u_scale + vec2(5.2, 1.3) - t, 4)); vec2 r = vec2(fbm(p * u_scale + q * u_warp * 2.0 + vec2(1.7, 9.2) + t * 0.6, 5), fbm(p * u_scale + q * u_warp * 2.0 + vec2(8.3, 2.8) - t * 0.4, 5)); float v = fbm(p * u_scale + r * u_warp * 2.0, 5); float shaped = sin(v * u_bands * 3.14159 + t * 1.5) * 0.5 + 0.5; shaped = mix(shaped, smoothstep(0.25, 0.75, shaped), u_softness); vec3 col = palRamp(shaped * 0.6 + length(r) * 0.25); col *= 0.35 + 0.75 * shaped; col += pal(4) * pow(shaped, 5.0) * u_glow; // Dark corners so the bloom has somewhere to sit. col *= 0.55 + 0.45 * exp(-dot(p, p) * 0.4); col = sigAir(col, p, smoothstep(0.0, 1.8, length(p))); col += sigGrain(uv); return vec4(col, 1.0); } `, }; export default plasmaBloom;