Actors and objects change only at camera cuts. int/bool/discrete params skip drift, lookahead and reactivity; discrete slowAxis steps on the section-held journey. Venues fade instead of toggling on interpolated popMul; roadside density is arrangement-only. DESIGN.md collects the project's design decisions; AGENTS.md points agents at it and the build-visualizer loop.
63 lines
2.4 KiB
JavaScript
63 lines
2.4 KiB
JavaScript
// Flow family: a drifting swarm of glowing motes advected along a curl-noise
|
|
// field. Each mote rides a divergence-free curl flow and wanders on top of it,
|
|
// so the swarm pools and diverges like embers on a breeze rather than orbiting.
|
|
//
|
|
// A base field is always present so the scene stands alone before any feedback
|
|
// has converged; the motes just make the movement legible.
|
|
|
|
export const fireflyDrift = {
|
|
name: 'Firefly Drift',
|
|
family: 'flow',
|
|
kind: 'fragment',
|
|
// Personality: see look/Personality.js.
|
|
consumes: ['cast', 'ink', 'staging'],
|
|
traits: ['camera', 'style'],
|
|
|
|
params: {
|
|
count: { type: 'float', range: [6, 48], default: 22, uniform: 'u_count', bias: 'density', discrete: true },
|
|
speed: { type: 'float', range: [0.05, 0.8], default: 0.3, uniform: 'u_speed', bias: 'motion', rate: true },
|
|
jitter: { type: 'float', range: [0, 0.4], default: 0.12, uniform: 'u_jitter' },
|
|
spread: { type: 'float', range: [0.4, 1.3], default: 0.95, uniform: 'u_spread' },
|
|
palette: { type: 'palette', count: 4 },
|
|
},
|
|
|
|
reactive: {
|
|
jitter: { feature: 'bandHigh', amount: 0.2, response: 'smooth' },
|
|
},
|
|
|
|
shader: `
|
|
vec4 scene(vec2 uv, vec2 p) {
|
|
float t = u_time * u_speed + u_seed;
|
|
p = sigCamera(p);
|
|
|
|
// Soft ambient wash so the frame is never black, even standing alone.
|
|
vec3 col = pal(0) * (0.06 + 0.05 * fbm(p * 1.5 + vec2(0.0, t * 0.3), 3));
|
|
|
|
for (int i = 0; i < 48; i++) {
|
|
if (float(i) >= u_count) break;
|
|
float fi = float(i);
|
|
|
|
// The mote's home is the song's lattice; the drift is this scene's own.
|
|
vec3 node = stageNode(fi, u_count);
|
|
vec2 base = node.xy * u_spread * vec2(1.0, 0.7);
|
|
|
|
// Advect along the curl field plus a bounded wander term on top.
|
|
vec2 flow = curl(node.xy * 3.0 + vec2(0.0, t * 0.15), t * 0.5);
|
|
vec2 pos = base + flow * 1.3
|
|
+ vec2(sin(t * (0.4 + fract(fi * 0.13))),
|
|
cos(t * (0.5 + fract(fi * 0.29)))) * u_jitter;
|
|
|
|
// A mote is one of the chorus, drawn small — the glow is the scene's
|
|
// contribution, the form is the song's.
|
|
float size = 0.045 * node.z;
|
|
float sd = castChorus((p - pos) / max(size, 1e-3)) * size;
|
|
float d = length(p - pos);
|
|
|
|
vec3 hc = pal(int(mod(fi, 4.0)));
|
|
col = mix(col, hc, inkMask(sd, uv));
|
|
}
|
|
|
|
return vec4(inkValue(col), 1.0);
|
|
}
|
|
`,
|
|
}; |