// 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. 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' }, haze: { type: 'float', range: [0, 1], default: 0.5, uniform: 'u_haze' }, 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' }, haze: { feature: 'beat', amount: 0.2, response: 'spike' }, }, 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 - u_haze * (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) * u_haze; } col += sigGrain(uv); return vec4(col, 1.0); } `, }; export default ridgeTerrain;