worldmap-viewer

git clone https://git.godosa.eu/worldmap-viewer

master

raw · 2283 bytes

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