diff --git a/config.js b/config.js index 778ffb6..d32fae5 100644 --- a/config.js +++ b/config.js @@ -335,14 +335,6 @@ window.CONFIG = { start: 0.35, // world units: clouds fade out very close to camera end: 2.5 // full density from this distance onward }, - // Terrain-following cloud base. The DEM height grid is sampled in - // the cloud shader, so the cloud bottom rises locally to keep a - // clearance above the visible ground. 'bottom' remains the global - // floor for areas without terrain data. - groundFollow: { - enabled: true, // false = flat cloud deck - clearanceM: 50 // metres above terrain, exaggerated with terrain - }, // Coverage per weather level, 0 = clear, 1 = overcast. Only the // levels listed here override the built-in defaults // (sunny 0.20, cloudy 0.70, stormy 0.80, night 0.45). Live weather diff --git a/vendor/clouds3d.js b/vendor/clouds3d.js index 30e0ece..8074cef 100644 --- a/vendor/clouds3d.js +++ b/vendor/clouds3d.js @@ -85,10 +85,6 @@ var FRAG_SRC = [ 'uniform float uSunAlt;', 'uniform float uCloudTop;', // cloud deck upper edge (world Y) 'uniform float uCloudBot;', // cloud deck lower edge (world Y) - 'uniform float uCloudGroundFollow;', - 'uniform float uCloudClearanceUnits;', - 'float terrElev(vec2 xz);', - 'float cloudBaseY(vec2 xz);', 'uniform float uCloudNearFadeStart;', 'uniform float uCloudNearFadeEnd;', 'uniform sampler2D uElev;', // terrarium RGB height grid, same UV as uGround @@ -234,9 +230,9 @@ var FRAG_SRC = [ 'float d = fbm3(cp * 1.80 + vec3(uTime * 0.015, 7.3, uTime * 0.012));', 'n = n + d * mix(0.22, 0.0, soft / 0.75);', '}', - // Cloud layer between the terrain-following base and uCloudTop. - 'float bot = cloudBaseY(p.xz);', - 'float h = clamp((py - bot) / max(0.01, uCloudTop - bot), 0.0, 1.0);', + // Cloud layer between uCloudBot and uCloudTop, densest in the + // middle (bell curve). The layer follows the Earth curvature. + 'float h = clamp((py - uCloudBot) / (uCloudTop - uCloudBot), 0.0, 1.0);', 'float profile = 4.0 * h * (1.0 - h); // bell curve', 'profile = max(profile, 0.0);', 'return smoothstep(baseThresh, baseThresh + 0.34 + soft * 0.28, n) * profile;', @@ -270,14 +266,6 @@ var FRAG_SRC = [ 'vec3 t = texture2D(uElev, euv).rgb;', 'return (t.r * 256.0 + t.g + t.b / 256.0) * 255.0 - 32768.0;', '}', - 'float cloudBaseY(vec2 xz) {', - 'float base = uCloudBot;', - 'if (uCloudGroundFollow > 0.5 && uElevOn > 0.5) {', - 'float terrainY = terrElev(xz) * uElevScale;', - 'base = max(base, terrainY + uCloudClearanceUnits);', - '}', - 'return min(base, uCloudTop - 0.05);', - '}', 'vec2 curvedLayerRoots(float layerY, vec3 ro, vec3 rd) {', 'float R = max(1.0, uEarthRadius);', 'float a = (uCurvatureOn > 0.5) ? dot(rd.xz, rd.xz) / (2.0 * R) : 0.0;', @@ -433,8 +421,7 @@ var FRAG_SRC = [ 'float d = fbm3(q * 1.80 + vec3(uTime * 0.015, 7.3, uTime * 0.012));', 'n = n + d * mix(0.22, 0.0, soft / 0.75);', '}', - 'float bot = cloudBaseY(p.xz);', - 'float h = clamp((alt - bot) / max(0.01, uCloudTop - bot), 0.0, 1.0);', + 'float h = clamp((alt - uCloudBot) / max(0.01, uCloudTop - uCloudBot), 0.0, 1.0);', 'float profile = 4.0 * h * (1.0 - h);', 'profile = max(profile, 0.0);', 'return smoothstep(baseThresh, baseThresh + 0.34 + soft * 0.28, n) * profile;', @@ -738,8 +725,7 @@ var FRAG_SRC = [ 'float soft = smoothstep(4.0, 20.0, t);', 'float d = cloudDensitySpherical(p, alt, baseThresh, soft);', 'if (d > 0.02) {', - 'float botHere = cloudBaseY(p.xz);', - 'float lit = clamp((alt - botHere) / max(0.01, uCloudTop - botHere), 0.0, 1.0);', + 'float lit = clamp((alt - uCloudBot) / max(0.01, uCloudTop - uCloudBot), 0.0, 1.0);', 'vec3 albC = uCloudAlbedo * mix(0.78, 1.0, lit);', 'float selfLit = clamp(1.0 - d * 0.8, 0.18, 1.0);', 'vec3 direct = albC * uSunColor * uSunInt * phase * sunUp * selfLit;', @@ -848,14 +834,6 @@ var CLOUD_SAMPLER_GLSL = [ 'vec3 t = texture2D(uElev, euv).rgb;', 'return (t.r * 256.0 + t.g + t.b / 256.0) * 255.0 - 32768.0;', '}', - 'float cloudBaseYT(vec2 xz) {', - 'float base = uCloudBot;', - 'if (uCloudGroundFollow > 0.5) {', - 'float terrainY = terrElevT(xz) * uElevScale;', - 'base = max(base, terrainY + uCloudClearanceUnits);', - '}', - 'return min(base, uCloudTop - 0.05);', - '}', // Terrain self-shadow: march from the surface towards the sun over the // height field and keep the smallest clearance between ray and ground. // The clearance (not a hard hit test) gives a soft penumbra, and the @@ -909,8 +887,7 @@ var CLOUD_SAMPLER_GLSL = [ 'float d = fbm3(cp * 1.80 + vec3(uTime * 0.015, 7.3, uTime * 0.012));', 'n = n + d * mix(0.22, 0.0, soft / 0.75);', '}', - 'float bot = cloudBaseYT(p.xz);', - 'float h = clamp((py - bot) / max(0.01, uCloudTop - bot), 0.0, 1.0);', + 'float h = clamp((py - uCloudBot) / (uCloudTop - uCloudBot), 0.0, 1.0);', 'float profile = 4.0 * h * (1.0 - h);', 'profile = max(profile, 0.0);', 'return smoothstep(baseThresh, baseThresh + 0.34 + soft * 0.28, n) * profile;', @@ -937,8 +914,6 @@ var TERRAIN_FRAG_SRC = [ 'uniform vec3 uWind;', // cloud advection vector, world units / s 'uniform float uCloudBot;', 'uniform float uCloudTop;', - 'uniform float uCloudGroundFollow;', - 'uniform float uCloudClearanceUnits;', 'uniform float uDensity;', // cloud coverage, same as the sky pass 'uniform float uCloudShadowOn;', 'uniform float uCloudShadowDensity;', // optical depth per density sample @@ -1170,8 +1145,6 @@ function init(canvas) { var uSunAlt = gl.getUniformLocation(prog, 'uSunAlt'); var uCloudTop = gl.getUniformLocation(prog, 'uCloudTop'); var uCloudBot = gl.getUniformLocation(prog, 'uCloudBot'); - var uCloudGroundFollow = gl.getUniformLocation(prog, 'uCloudGroundFollow'); - var uCloudClearanceUnits = gl.getUniformLocation(prog, 'uCloudClearanceUnits'); var uElev = gl.getUniformLocation(prog, 'uElev'); var uElevOn = gl.getUniformLocation(prog, 'uElevOn'); var uElevScale = gl.getUniformLocation(prog, 'uElevScale'); @@ -1295,8 +1268,6 @@ function init(canvas) { var terrainUwind = terrainProg ? gl.getUniformLocation(terrainProg, 'uWind') : null; var terrainUcloudbot = terrainProg ? gl.getUniformLocation(terrainProg, 'uCloudBot') : null; var terrainUcloudtop = terrainProg ? gl.getUniformLocation(terrainProg, 'uCloudTop') : null; - var terrainUcloudfollow = terrainProg ? gl.getUniformLocation(terrainProg, 'uCloudGroundFollow') : null; - var terrainUcloudclearance = terrainProg ? gl.getUniformLocation(terrainProg, 'uCloudClearanceUnits') : null; var terrainUdensity = terrainProg ? gl.getUniformLocation(terrainProg, 'uDensity') : null; var terrainUcloudshadow = terrainProg ? gl.getUniformLocation(terrainProg, 'uCloudShadowOn') : null; var terrainUcsDens = terrainProg ? gl.getUniformLocation(terrainProg, 'uCloudShadowDensity') : null; @@ -1336,7 +1307,6 @@ function init(canvas) { uSpeed: uSpeed, uDensity: uDensity, uDayProgress: uDayProgress, uSunAlt: uSunAlt, uCloudTop: uCloudTop, uCloudBot: uCloudBot, - uCloudGroundFollow: uCloudGroundFollow, uCloudClearanceUnits: uCloudClearanceUnits, uCloudNearFadeStart: gl.getUniformLocation(prog, 'uCloudNearFadeStart'), uCloudNearFadeEnd: gl.getUniformLocation(prog, 'uCloudNearFadeEnd'), uElev: uElev, uElevOn: uElevOn, uElevScale: uElevScale, uTerrainExag: uTerrainExag, @@ -1402,7 +1372,6 @@ function init(canvas) { uStarAmb: terrainUstarAmb, uTime: terrainUtime, uWind: terrainUwind, uCloudBot: terrainUcloudbot, uCloudTop: terrainUcloudtop, uDensity: terrainUdensity, - uCloudGroundFollow: terrainUcloudfollow, uCloudClearanceUnits: terrainUcloudclearance, uCloudShadowOn: terrainUcloudshadow, uCloudShadowDensity: terrainUcsDens, uCloudShadowFloor: terrainUcsFloor, @@ -1584,11 +1553,6 @@ var TERRAIN_EXAG = (typeof TERRAIN_CFG.exaggeration === 'number' && TERRAIN_CFG.exaggeration > 0) ? TERRAIN_CFG.exaggeration : 8; // metres -> world units, including the vertical exaggeration var ELEV_SCALE_UNITS = TERRAIN_EXAG / (KM_PER_TILE * 1000.0); -var CLOUD_GROUND_FOLLOW_CFG = (window.CONFIG && window.CONFIG.clouds && window.CONFIG.clouds.groundFollow) || {}; -var CLOUD_GROUND_FOLLOW = CLOUD_GROUND_FOLLOW_CFG.enabled === true ? 1.0 : 0.0; -var CLOUD_CLEARANCE_M = (typeof CLOUD_GROUND_FOLLOW_CFG.clearanceM === 'number') - ? Math.max(0, CLOUD_GROUND_FOLLOW_CFG.clearanceM) : 50; -var CLOUD_CLEARANCE_UNITS = CLOUD_CLEARANCE_M * ELEV_SCALE_UNITS; var ORBIT_CFG = (window.CONFIG && window.CONFIG.orbit) || null; var ORBIT_R = 0; // figure-8 half-diagonal (lobe tip reach) in tiles @@ -7420,8 +7384,6 @@ window.clouds3dRender = function(target) { gl.uniform1f(s.uCloudBot, CLOUD_BOT); gl.uniform1f(s.uCloudNearFadeStart, CLOUD_NEAR_FADE_START); gl.uniform1f(s.uCloudNearFadeEnd, CLOUD_NEAR_FADE_END); - gl.uniform1f(s.uCloudGroundFollow, CLOUD_GROUND_FOLLOW); - gl.uniform1f(s.uCloudClearanceUnits, CLOUD_CLEARANCE_UNITS); // Ground mosaic uniforms + periodic re-fetch trigger. // uGroundCenter is the world position (X, Z) of the centre tile's @@ -7694,8 +7656,6 @@ window.clouds3dRender = function(target) { gl.uniform3f(terr.uWind, _cloudWind[0], _cloudWind[1], _cloudWind[2]); gl.uniform1f(terr.uCloudBot, CLOUD_BOT); gl.uniform1f(terr.uCloudTop, CLOUD_TOP); - gl.uniform1f(terr.uCloudGroundFollow, CLOUD_GROUND_FOLLOW); - gl.uniform1f(terr.uCloudClearanceUnits, CLOUD_CLEARANCE_UNITS); gl.uniform1f(terr.uDensity, density); gl.uniform1f(terr.uCloudShadowOn, ATMO_CLOUD_SHADOWS ? 1.0 : 0.0); gl.uniform1f(terr.uCloudShadowDensity, ATMO_CS_DENSITY);