From 6bedc2c95ce50e470d00b0996802922008dcbfed Mon Sep 17 00:00:00 2001 From: Richard Zink Date: Tue, 13 Oct 2026 14:46:06 +0200 Subject: [PATCH] config: reduce far cloud softening --- config.js | 8 ++++++++ vendor/clouds3d.js | 18 +++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/config.js b/config.js index 91764cd..4c7093f 100644 --- a/config.js +++ b/config.js @@ -335,6 +335,14 @@ window.CONFIG = { start: 0.35, // world units: clouds fade out very close to camera end: 2.5 // full density from this distance onward }, + // Far softening reduces detail/noise at long view distances. Lower + // max keeps the deck denser near the horizon and can remove the + // transparent ring around the terrain edge. + farSoft: { + start: 4, // world units where far softening begins + end: 20, // world units where max softening is reached + max: 0.35 // 1 = old behaviour, 0 = no far softening + }, // Delay the volumetric cloud pass until the DEM/terrain mesh is // ready. This avoids clouds appearing over an unfinished ground model. waitForTerrain: true, // false = draw clouds immediately diff --git a/vendor/clouds3d.js b/vendor/clouds3d.js index 1310008..fe051a8 100644 --- a/vendor/clouds3d.js +++ b/vendor/clouds3d.js @@ -87,6 +87,9 @@ var FRAG_SRC = [ 'uniform float uCloudBot;', // cloud deck lower edge (world Y) 'uniform float uCloudNearFadeStart;', 'uniform float uCloudNearFadeEnd;', + 'uniform float uCloudFarSoftStart;', + 'uniform float uCloudFarSoftEnd;', + 'uniform float uCloudFarSoftMax;', 'uniform sampler2D uElev;', // terrarium RGB height grid, same UV as uGround 'uniform float uElevOn;', // terrain enabled (0/1) 'uniform float uElevScale;', // metres -> world units (incl. exaggeration) @@ -723,7 +726,7 @@ var FRAG_SRC = [ 'p += rd * (ign(gl_FragCoord.xy + vec2(float(i) * 7.13, float(i) * 3.71)) - 0.5) * stepSize * 0.25;', 'float alt = p.y + earthDrop(p.xz);', 'if (alt > uCloudTop + 0.1 || alt < uCloudBot - 0.1) break;', - 'float soft = smoothstep(4.0, 20.0, t);', + 'float soft = smoothstep(uCloudFarSoftStart, uCloudFarSoftEnd, t) * uCloudFarSoftMax;', 'float d = cloudDensitySpherical(p, alt, baseThresh, soft);', 'if (d > 0.02) {', 'float lit = clamp((alt - uCloudBot) / max(0.01, uCloudTop - uCloudBot), 0.0, 1.0);', @@ -1310,6 +1313,9 @@ function init(canvas) { uCloudTop: uCloudTop, uCloudBot: uCloudBot, uCloudNearFadeStart: gl.getUniformLocation(prog, 'uCloudNearFadeStart'), uCloudNearFadeEnd: gl.getUniformLocation(prog, 'uCloudNearFadeEnd'), + uCloudFarSoftStart: gl.getUniformLocation(prog, 'uCloudFarSoftStart'), + uCloudFarSoftEnd: gl.getUniformLocation(prog, 'uCloudFarSoftEnd'), + uCloudFarSoftMax: gl.getUniformLocation(prog, 'uCloudFarSoftMax'), uElev: uElev, uElevOn: uElevOn, uElevScale: uElevScale, uTerrainExag: uTerrainExag, uSunDir: uSunDir, uMoonDir: uMoonDir, uMode: uMode, uAtmoModelOn: uAtmoModelOn, uAtmoHeightUnits: uAtmoHeightUnits, @@ -1502,8 +1508,15 @@ if (window.CONFIG && window.CONFIG.clouds) { CLOUD_TOP = Math.max(0.2, Math.min(CLOUD_TOP, 2.0)); CLOUD_BOT = Math.min(CLOUD_BOT, CLOUD_TOP - 0.4); var CLOUD_NEAR_FADE_CFG = (window.CONFIG && window.CONFIG.clouds && window.CONFIG.clouds.nearFade) || {}; +var CLOUD_FAR_SOFT_CFG = (window.CONFIG && window.CONFIG.clouds && window.CONFIG.clouds.farSoft) || {}; var CLOUD_NEAR_FADE_START = (typeof CLOUD_NEAR_FADE_CFG.start === 'number') ? Math.max(0, CLOUD_NEAR_FADE_CFG.start) : 0.35; var CLOUD_NEAR_FADE_END = Math.max(CLOUD_NEAR_FADE_START + 0.1, (typeof CLOUD_NEAR_FADE_CFG.end === 'number') ? CLOUD_NEAR_FADE_CFG.end : 2.5); +var CLOUD_FAR_SOFT_START = (typeof CLOUD_FAR_SOFT_CFG.start === 'number') + ? Math.max(0.1, CLOUD_FAR_SOFT_CFG.start) : 4.0; +var CLOUD_FAR_SOFT_END = (typeof CLOUD_FAR_SOFT_CFG.end === 'number') + ? Math.max(CLOUD_FAR_SOFT_START + 0.1, CLOUD_FAR_SOFT_CFG.end) : 20.0; +var CLOUD_FAR_SOFT_MAX = (typeof CLOUD_FAR_SOFT_CFG.max === 'number') + ? Math.max(0.0, Math.min(1.0, CLOUD_FAR_SOFT_CFG.max)) : 1.0; var CLOUDS_ON = !(window.CONFIG && window.CONFIG.clouds && window.CONFIG.clouds.enabled === false); var CLOUDS_WAIT_FOR_TERRAIN = !(window.CONFIG && window.CONFIG.clouds && window.CONFIG.clouds.waitForTerrain === false); var CLOUD_TERRAIN_OCCLUSION = !(window.CONFIG && window.CONFIG.clouds && window.CONFIG.clouds.terrainOcclusion === false); @@ -7390,6 +7403,9 @@ 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.uCloudFarSoftStart, CLOUD_FAR_SOFT_START); + gl.uniform1f(s.uCloudFarSoftEnd, CLOUD_FAR_SOFT_END); + gl.uniform1f(s.uCloudFarSoftMax, CLOUD_FAR_SOFT_MAX); // Ground mosaic uniforms + periodic re-fetch trigger. // uGroundCenter is the world position (X, Z) of the centre tile's