// STAGE: a constellation. The chorus, scattered, drifting, joined by the light
// between them.
//
// Where Procession is regular, this is the scattered lattice: a point set that
// wanders, with the song's second cast member at every node.

export const constellation = {
    name: 'Constellation',
    family: 'minimal',
    kind: 'fragment',
    consumes: ['cast', 'ink', 'staging'],
    texture: 0.6,
    traits: ['shape', 'camera', 'space', 'style'],

    params: {
        count:    { type: 'int',   range: [6, 40],     default: 16,  uniform: 'u_count', bias: 'density' },
        size:     { type: 'float', range: [0.02, 0.16],default: 0.06,uniform: 'u_size' },
        drift:    { type: 'float', range: [0.02, 0.6], default: 0.12,uniform: 'u_drift', bias: 'motion', rate: true },
        spread:   { type: 'float', range: [0.4, 1.4],  default: 0.95,uniform: 'u_spread' },
        link:     { type: 'float', range: [0, 1],      default: 0.35,uniform: 'u_link', bias: 'energy' },
        twinkle:  { type: 'float', range: [0, 1],      default: 0.4, uniform: 'u_twinkle' },
        palette:  { type: 'palette', count: 4 },
    },

    reactive: {
        twinkle: { feature: 'bandHigh', amount: 0.5 },
        size:    { feature: 'beat', amount: 0.12, response: 'spike' },
    },

    shader: `
vec4 scene(vec2 uv, vec2 p) {
    p = sigCamera(p);
    float t = u_time * u_drift + u_seed;

    vec3 col = pal(0) * 0.12;
    col = sigAir(col, p, 0.5);

    float glow = 0.0;

    for (int i = 0; i < 40; i++) {
        if (i >= u_count) break;
        float fi = float(i);
        vec2 h = hash22(vec2(fi + u_seed, fi * 1.7));

        // Homes come from the song's lattice — the stage owns the wander, not
        // the composition. A slow drift around a fixed home, so the
        // constellation keeps its shape while nothing in it is ever quite still.
        vec3 node = stageNode(fi, float(u_count));
        vec2 pos = node.xy * u_spread
                 + vec2(sin(t + h.x * 6.28), cos(t * 0.83 + h.y * 6.28)) * 0.08;

        float pulse = 0.7 + 0.3 * sin(t * 2.0 + fi) * u_twinkle;
        float size = u_size * node.z * pulse;

        vec2 q = (p - pos) / max(size, 1e-3);
        float d = castChorus(q) * size;

        float a = inkMask(d, uv);
        col = mix(col, pal(i + 1), a);

        // The light between them: what makes this a constellation and not a
        // scatter of dots.
        glow += u_link * 0.006 / (0.01 + abs(d));
    }

    col += pal(2) * glow * 0.35;
    return vec4(inkValue(col), 1.0);
}
`,
};

export default constellation;
