// Terrain surface materials, shared by the map's colour shader and the density
// preview probe.
//
// MOVED HERE, NOT COPIED. The probe exists to judge how the terrain will look
// before the shading is wired into a map; a probe that colours with its own
// private copy of the ramp is judging something the game does not render. One
// definition, two consumers.
float sstep2(float a, float b, float x) {
float t = clamp((x - a) / (b - a), 0.0, 1.0);
return t * t * (3.0 - 2.0 * t);
}
// terrain-lookdev/index.html computeAlbedo(), transcribed. THREE attributes:
// altitude t, slope, and curvature k (0 crease .. 1 ridge). Concave ground
// collects water and grows things; convex ground sheds both and shows rock.
vec3 lookdev_material(float t, float slope, float k) {
const vec3 GRASS = vec3(0.20, 0.30, 0.13);
const vec3 MEADOW = vec3(0.33, 0.40, 0.17);
const vec3 DRY = vec3(0.47, 0.43, 0.26);
const vec3 SCREE = vec3(0.44, 0.40, 0.36);
const vec3 ROCK = vec3(0.34, 0.31, 0.30);
const vec3 ROCK_L = vec3(0.52, 0.49, 0.46);
const vec3 SNOW = vec3(0.95, 0.96, 0.98);
const vec3 WET = vec3(0.16, 0.19, 0.15);
float rock = sstep2(0.30, 0.85, slope);
// snow lies later on steep ground and later in creases where it is shaded
float snowline = 0.58 + 0.22 * rock;
float snow = sstep2(snowline, snowline + 0.16, t) * (1.0 - 0.7 * rock);
// creases are wet: darker, greener, and they hold vegetation higher
float wet = sstep2(0.55, 0.10, k);
vec3 veg = t < 0.5 ? mix(GRASS, MEADOW, sstep2(0.0, 0.5, t))
: mix(MEADOW, DRY, sstep2(0.5, 0.85, t));
veg = mix(veg, WET, 0.55 * wet);
vec3 rk = mix(ROCK, ROCK_L, sstep2(0.45, 1.0, k));
rk = mix(rk, SCREE, sstep2(0.75, 0.35, k) * 0.5);
vec3 a = mix(veg, rk, rock);
vec3 b = mix(a, SNOW, snow);
float ao = 0.72 + 0.28 * sstep2(0.15, 0.85, k); // creases in their own shadow
return b * ao;
}
const int LAND_N = 7;
const int SEA_N = 6;
vec3 hypso_ramp(float y) {
// Land, above sea level.
float le[7] = float[](0.0, 300.0, 800.0, 1600.0, 2600.0, 3600.0, 6500.0);
vec3 lc[7] = vec3[](vec3(0.29, 0.48, 0.25), vec3(0.49, 0.60, 0.29),
vec3(0.72, 0.63, 0.35), vec3(0.66, 0.46, 0.25),
vec3(0.55, 0.44, 0.38), vec3(0.91, 0.91, 0.94),
vec3(1.00, 1.00, 1.00));
// Sea, below it, on its OWN scale so it gets the full range.
float se[6] = float[](0.0, -200.0, -1000.0, -2500.0, -4500.0, -9000.0);
vec3 sc[6] = vec3[](vec3(0.47, 0.68, 0.74), vec3(0.31, 0.53, 0.63),
vec3(0.19, 0.37, 0.52), vec3(0.11, 0.24, 0.38),
vec3(0.05, 0.13, 0.24), vec3(0.02, 0.06, 0.14));
if (y > 0.0) {
if (y >= le[LAND_N - 1]) { return lc[LAND_N - 1]; }
for (int i = 0; i < LAND_N - 1; i++) {
if (y < le[i + 1]) {
float t = (y - le[i]) / max(le[i + 1] - le[i], 0.001);
return mix(lc[i], lc[i + 1], t);
}
}
return lc[0];
}
if (y <= se[SEA_N - 1]) { return sc[SEA_N - 1]; }
for (int i = 0; i < SEA_N - 1; i++) {
if (y > se[i + 1]) {
float t = (y - se[i]) / min(se[i + 1] - se[i], -0.001);
return mix(sc[i], sc[i + 1], t);
}
}
return sc[0];
}