// Minimal family: an empty plain under a very large sky, with one distant form
// standing on the horizon.
//
// The emptiest scene in the library and the most deliberate about it — most of
// the frame is a gradient. Distinct from Horizon Lines (a bundle of lines) and
// Ridge Terrain (layered silhouettes): there is exactly one object, it is small,
// and it is far away. What moves is the light and the heat shimmer.
//
// The object is the track's signature form, so the thing on the horizon of a
// hexagonal video is a hexagon.

export const saltFlat = {
    name: 'Salt Flat',
    family: 'minimal',
    kind: 'fragment',
    consumes: ['cast', 'ink'],
    traits: ['shape', 'camera', 'space', 'style'],

    params: {
        monolith: { type: 'float', range: [0.0, 0.35], default: 0.12, uniform: 'u_monolith' },
        standing: { type: 'float', range: [-0.7, 0.7], default: 0.0,  uniform: 'u_standing' },
        shimmer:  { type: 'float', range: [0, 0.09],   default: 0.025,uniform: 'u_shimmer' },
        ground:   { type: 'float', range: [0, 1],      default: 0.4,  uniform: 'u_ground' },
        salt:     { type: 'float', range: [0, 1],      default: 0.35, uniform: 'u_salt', bias: 'density' },
        pace:     { type: 'float', range: [0.02, 0.5], default: 0.12, uniform: 'u_pace', bias: 'motion', rate: true },
        palette:  { type: 'palette', count: 5 },
    },

    reactive: {
        shimmer:  { feature: 'bandAir',  amount: 0.25 },
    },

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

    float horizon = sigHorizonY() * 0.6 - 0.15;

    // Heat shimmer: everything near the horizon wobbles, nothing else does.
    float nearHorizon = exp(-abs(p.y - horizon) * 5.0);
    p.x += sin(p.y * 60.0 + t * 6.0) * u_shimmer * nearHorizon;

    float above = p.y - horizon;

    // Sky: a tall gradient, darkest at the top.
    vec3 col = mix(pal(1) * 0.5, pal(0) * 0.25, sat(above * 0.8 + 0.15));

    // The glow band sitting on the horizon — the light source of the whole scene.

    if (above < 0.0) {
        float depth = sat(-above * 2.2);            // 0 far .. 1 near
        vec3 plain = mix(pal(2) * 0.5, pal(0) * 0.3, depth);

        // Salt crust: cracked cells, only legible in the near field.
        vec2 cellUv = vec2(p.x / max(-above * 0.9 + 0.06, 0.02), 1.0 / max(-above + 0.05, 0.02));
        float crack = abs(fract(cellUv.x * 0.5) - 0.5) + abs(fract(cellUv.y * 0.5) - 0.5);
        plain += pal(4) * smoothstep(0.42, 0.5, crack) * u_salt * depth * 0.25;

        // Reflection of the glow band, compressed toward the horizon.
        plain += pal(3) * exp(above * 7.0) * 0.45 * 0.3;

        col = mix(col, plain, u_ground);
    }

    // The one object: small, on the horizon, in the track's form.
    if (u_monolith > 0.005) {
        vec2 at = vec2(u_standing, horizon + u_monolith * 0.9);
        float d = castMain((p - at) / u_monolith) * u_monolith;
        col = mix(col, pal(0) * 0.12, smoothstep(0.006, -0.006, d));
        col += pal(4) * inkStroke(d) * (0.3 + 0.45 * 0.5);
    }

    col = sigAir(col, p, smoothstep(0.0, 1.4, abs(p.x)));
    return vec4(inkValue(col), 1.0);
}
`,
};

export default saltFlat;
