// 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.
    // Crisp line work: the track's surface grain would only fur the edges.
    texture: 0,
    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;
