// Minimal family: a sparse field of horizontal lines that bend around the // centre. Most of the frame is negative space, which is exactly what an intro or // a breakdown wants — the arc driver has nowhere restful to go otherwise. export const horizonLines = { name: 'Horizon Lines', family: 'minimal', kind: 'fragment', // Personality: see look/Personality.js. traits: ['space', 'camera', 'style'], params: { count: { type: 'float', range: [3, 40], default: 14, uniform: 'u_count', bias: 'density' }, thickness: { type: 'float', range: [0.002, 0.03], default: 0.008, uniform: 'u_thickness' }, bend: { type: 'float', range: [0, 1.2], default: 0.35, uniform: 'u_bend' }, speed: { type: 'float', range: [0.02, 0.4], default: 0.12, uniform: 'u_speed', bias: 'motion', rate: true }, spread: { type: 'float', range: [0.2, 1.4], default: 0.9, uniform: 'u_spread' }, glow: { type: 'float', range: [0, 1], default: 0.3, uniform: 'u_glow', bias: 'energy' }, palette: { type: 'palette', count: 4 }, }, reactive: { bend: { feature: 'bandLow', amount: 0.35, response: 'smooth' }, glow: { feature: 'beat', amount: 0.3, response: 'spike' }, }, shader: ` vec4 scene(vec2 uv, vec2 p) { float t = u_time * u_speed + u_seed; p = sigCamera(p); // The bundle sits on the track's horizon rather than in the middle of the // frame — this scene is nothing but a horizon, so it should be the shared one. p.y -= sigHorizonY() * 0.6; // Displace vertically by a slow wave, strongest at the centre of the frame. float envelope = exp(-p.x * p.x * 1.2); float offset = sin(p.x * 2.2 + t * 2.0) * u_bend * envelope; vec3 col = pal(0) * 0.06; float total = 0.0; for (int i = 0; i < 40; i++) { if (float(i) >= u_count) break; float fi = float(i); float slot = (fi / max(u_count - 1.0, 1.0) - 0.5) * 2.0 * u_spread; float y = slot + offset * (0.4 + fract(fi * 0.37)); float d = abs(p.y - y); float line = smoothstep(u_thickness * (0.5 + u_sigLine), 0.0, d); float halo = exp(-d * 26.0) * u_glow; vec3 c = pal(i); col += c * (line + halo * 0.55); total += line; } // Keep the far edges dark so the lines read as a subject, not wallpaper. col *= 0.55 + 0.45 * exp(-dot(p, p) * 0.5); col = sigAir(col, p, smoothstep(0.0, 1.6, abs(p.y))); col += sigGrain(uv); return vec4(col, 1.0); } `, }; export default horizonLines;