// Structural family: layered ridge silhouettes receding to a horizon.
//
// Cheap fake depth — parallax layers rather than a raymarch — which keeps it
// affordable at 4K while still reading as a place rather than a pattern.

export const ridgeTerrain = {
    name: 'Ridge Terrain',
    family: 'structural',
    kind: 'fragment',
    // Personality: see look/Personality.js.
    consumes: ['ink'],
    traits: ['space', 'camera', 'style'],

    params: {
        layers:   { type: 'int',   range: [2, 10],   default: 6,   uniform: 'u_layers', bias: 'density' },
        height:   { type: 'float', range: [0.1, 0.8], default: 0.35, uniform: 'u_height', bias: 'energy' },
        rough:    { type: 'float', range: [1, 6],    default: 2.5, uniform: 'u_rough' },
        speed:    { type: 'float', range: [0.01, 0.3], default: 0.06, uniform: 'u_speed', bias: 'motion', rate: true },
        horizon:  { type: 'float', range: [-0.4, 0.4], default: 0.0, uniform: 'u_horizon' },
        stars:    { type: 'float', range: [0, 1],    default: 0.3, uniform: 'u_stars' },
        palette:  { type: 'palette', count: 6 },
    },

    reactive: {
        height: { feature: 'bandLow',  amount: 0.25, response: 'smooth' },
    },

    shader: `
vec4 scene(vec2 uv, vec2 p) {
    float t = u_time * u_speed + u_seed;
    p = sigCamera(p);
    // Its own horizon param decides the framing; the track decides where the
    // ground actually is, so two scenes with a horizon agree on one.
    float horizon = clamp(u_horizon + sigHorizonY() * 0.35, -0.85, 0.85);

    // Sky gradient above the horizon.
    float sky = sat((p.y - horizon) * 0.8 + 0.5);
    vec3 col = mix(pal(0) * 0.35, pal(1) * 0.18, sky);

    // Sparse stars, only in the upper sky, fading as haze rises.
    if (u_stars > 0.01 && p.y > horizon) {
        vec2 cell = floor(uv * 220.0);
        float rnd = hash12(cell);
        float star = step(0.9975, rnd) * sat((p.y - horizon) * 2.0);
        col += vec3(star) * u_stars * (0.6 + 0.4 * sin(t * 8.0 + rnd * 30.0));
    }

    // Ridges, far to near. Each is a 1D fbm silhouette.
    for (int i = 0; i < 10; i++) {
        if (i >= u_layers) break;
        float fi = float(i);
        float depth = fi / float(max(u_layers - 1, 1));      // 0 far .. 1 near

        float parallax = mix(0.15, 1.0, depth);
        float x = p.x * mix(0.6, 1.8, depth) + t * parallax + fi * 13.7;

        float ridge = fbm(vec2(x, fi * 5.1) * u_rough, 4) - 0.5;
        float base = horizon - depth * 0.28;
        float top = base + ridge * u_height * mix(0.5, 1.3, depth);

        float mask = smoothstep(0.004, 0.0, p.y - top);
        vec3 tint = mix(pal(2), pal(4), depth);
        // Distant layers wash out toward the sky colour.
        tint = mix(mix(pal(1) * 0.4, tint, 0.35 + depth * 0.65), tint, 1.0 - 0.5 * (1.0 - depth));

        col = mix(col, tint * (0.25 + depth * 0.75), mask);

        // Rim light along each crest.
        col += pal(5) * smoothstep(0.02, 0.0, abs(p.y - top)) * (0.12 + depth * 0.25) * 0.5;
    }

    return vec4(inkValue(col), 1.0);
}
`,
};

export default ridgeTerrain;
