// shading.js — fragment shading shared by both views and the deep-zoom tiles: base texture, optional over-layer,
// then sun lighting (Sky on) or the plain v1 look (limb factor only).
import * as THREE from 'three';
import { R_KM } from './geo.js';
import { HAZE_KM } from './atmosphere.js';
export const SHADE_GLSL = /* glsl */ `
uniform sampler2D map;
uniform sampler2D map2;
uniform float hasMap;
uniform float mix2;
uniform vec3 sunDir;
uniform float sky;
uniform vec3 camPos;
uniform vec3 hazeCol;
uniform float hazeAmt;
uniform float hazeK;
vec3 overColor(vec3 c, vec3 o, float k) {
float l = dot(c, vec3(0.299, 0.587, 0.114));
vec3 g = mix(c, vec3(l), min(1.0, 2.0 * k));
return mix(g, o * clamp(0.55 + 0.9 * l, 0.0, 1.0), k);
}
vec3 lightColor(vec2 uv, vec3 n, float limb) {
vec3 c = mix(vec3(0.16, 0.2, 0.28), texture2D(map, uv).rgb, hasMap);
if (mix2 > 0.0) c = overColor(c, texture2D(map2, uv).rgb, mix2);
if (sky < 0.5) return c * limb;
float cz = dot(normalize(n), sunDir);
float day = smoothstep(-0.1, 0.1, cz);
vec3 lit = c * (0.8 + 0.2 * clamp(cz, 0.0, 1.0));
vec3 night = c * vec3(0.24, 0.27, 0.36);
return mix(night, lit, day) * mix(1.0, limb, 0.4);
}
vec3 shadeColor(vec2 uv, vec3 n, float limb) { // near the ground, distance fades into the horizon colour
vec3 c = lightColor(uv, n, limb);
if (hazeAmt <= 0.0) return c;
return mix(c, hazeCol, hazeAmt * (1.0 - exp(-distance(n, camPos) * hazeK)));
}`;
export function shadeUniforms() {
return { map: { value: null }, map2: { value: null }, hasMap: { value: 0 }, mix2: { value: 0 },
sunDir: { value: new THREE.Vector3(1, 0, 0) }, sky: { value: 0 },
camPos: { value: new THREE.Vector3() }, hazeCol: { value: new THREE.Vector3(0.74, 0.83, 0.93) },
hazeAmt: { value: 0 }, hazeK: { value: R_KM / HAZE_KM } };
}
export function overMix(c, o, k) {
const l = 0.299 * c[0] + 0.587 * c[1] + 0.114 * c[2], d = Math.min(1, 2 * k), s = Math.min(1, Math.max(0, 0.55 + 0.9 * l));
return c.map((v, i) => { const g = v + (l - v) * d; return g + (o[i] * s - g) * k; });
}
export function applyOver(u, tex, op) {
u.map2.value = tex;
u.mix2.value = tex ? op : 0;
}
export function applySun(u, v) {
if (v) u.sunDir.value.set(v[0], v[1], v[2]);
u.sky.value = v ? 1 : 0;
}