// Ported from party-stage's "Floating Geometry". Shape count, size and motion // were fixed constants in the original; they are the whole point of the scene, // so they are now params the look generator can move. export const floatingGeometry = { name: 'Floating Geometry', family: 'geometric', kind: 'fragment', // Personality: see look/Personality.js. This scene is nothing but a handful // of shapes, so `shape` is the trait it exists to express. // Takes the track's surface grain, but lightly — this is drawn, not filmed. texture: 0.4, consumes: ['cast', 'ink', 'staging'], traits: ['shape', 'camera', 'style'], params: { count: { type: 'int', range: [2, 14], default: 6, uniform: 'u_count', bias: 'density' }, size: { type: 'float', range: [0.04, 0.3],default: 0.15,uniform: 'u_size' }, drift: { type: 'float', range: [0.1, 1.5], default: 0.4, uniform: 'u_drift', bias: 'motion', rate: true }, spin: { type: 'float', range: [0, 2], default: 0.6, uniform: 'u_spin', rate: true }, variety: { type: 'float', range: [0, 0.6], default: 0.25, uniform: 'u_variety' }, spread: { type: 'float', range: [0.3, 1.2], default: 0.8, uniform: 'u_spread' }, palette: { type: 'palette', count: 5 }, }, reactive: { size: { feature: 'beat', amount: 0.18, response: 'spike' }, }, shader: ` vec4 scene(vec2 uv, vec2 p) { float t = u_time * u_drift + u_seed; p = sigCamera(p); // Background wash from the two darkest palette entries. vec3 col = mix(pal(0) * 0.18, pal(1) * 0.24, sin(t) * 0.5 + 0.5); for (int i = 0; i < 14; i++) { if (i >= u_count) break; float fi = float(i); float s = u_seed + fi * 123.456; // The song's lattice sets where they hang; this scene keeps the float. vec3 node = stageNode(fi, float(u_count)); vec2 pos = node.xy * u_spread * vec2(1.0, 0.55) + vec2(sin(t * 0.5 + s), cos(t * 0.3 + s * 1.1)) * 0.18; vec2 sp = rot(t * (0.2 + fract(s) * u_spin)) * (p - pos); float size = u_size * node.z * (0.6 + fract(s * 0.7) * 0.8); // Every element is the song's protagonist. This scene used to pick // between a box and a circle per element, which is precisely the choice // the production design should be making — one video, one cast. // The variety param only scales them apart; it never changes what they are. float scale = size * (1.0 + (fract(s * 0.37) - 0.5) * u_variety); float d = castMain(sp / max(scale, 1e-3)) * scale; vec3 shapeColor = pal(i + int(floor(t * 0.3))); col = mix(col, shapeColor, inkMask(d, uv) * 0.85); col += shapeColor * (1.0 - smoothstep(0.0, size * 2.2, abs(d))) * 0.25; } return vec4(inkValue(col), 1.0); } `, }; export default floatingGeometry;