// 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; }