From 6802f83d1d450e409daf48e65757a2eb29fe895c Mon Sep 17 00:00:00 2001 From: Richard Zink Date: Mon, 12 Oct 2026 18:13:54 +0200 Subject: [PATCH] clouds: use curved cloud layer and allow clouds over terrain --- vendor/clouds3d.js | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/vendor/clouds3d.js b/vendor/clouds3d.js index ec93b65..cea9513 100644 --- a/vendor/clouds3d.js +++ b/vendor/clouds3d.js @@ -374,6 +374,27 @@ var FRAG_SRC = [ 'float sq = sqrt(disc);', 'return vec2((-b - sq) * 0.5, (-b + sq) * 0.5);', '}', + 'vec2 cloudLayerRoots(float layerY, vec3 rd) {', + 'float camY = uCamPos.y;', + 'if (uCurvatureOn < 0.5) {', + 'if (abs(rd.y) < 1e-5) return vec2(-1.0, -1.0);', + 'float t = (layerY - camY) / rd.y;', + 'return vec2(t, t);', + '}', + 'float R = max(1.0, uEarthRadius);', + 'float a = (rd.x * rd.x + rd.z * rd.z) / (2.0 * R);', + 'float b = rd.y;', + 'float c = camY - layerY;', + 'if (abs(a) < 1e-8) {', + 'if (abs(b) < 1e-5) return vec2(-1.0, -1.0);', + 'float t = -c / b;', + 'return vec2(t, t);', + '}', + 'float disc = b * b - 4.0 * a * c;', + 'if (disc < 0.0) return vec2(-1.0, -1.0);', + 'float sq = sqrt(disc);', + 'return vec2((-b - sq) / (2.0 * a), (-b + sq) / (2.0 * a));', + '}', 'float cloudDensitySpherical(vec3 p, float alt, float baseThresh, float soft) {', 'vec3 q = vec3(p.x, alt, p.z);', 'float n = fbm3(q * 0.22 + vec3(0.0, 0.0, uTime * 0.05));', @@ -629,12 +650,9 @@ var FRAG_SRC = [ 'if (uMode == 1) {', 'if (uCloudsOn < 0.5) { gl_FragColor = vec4(0.0); return; }', - 'float R = max(1.0, uEarthRadius);', - 'vec3 C = vec3(uCamPos.x, -R, uCamPos.z);', - 'vec3 oc = uCamPos - C;', - 'float camAlt = max(0.0, length(oc) - R);', - 'vec2 top = cloudShellRoots(uCloudTop, oc, rd);', - 'vec2 bot = cloudShellRoots(uCloudBot, oc, rd);', + 'float camAlt = uCamPos.y;', + 'vec2 top = cloudLayerRoots(uCloudTop, rd);', + 'vec2 bot = cloudLayerRoots(uCloudBot, rd);', 'float tEnter = 1e9;', 'float tExit = -1e9;', 'if (camAlt >= uCloudBot && camAlt <= uCloudTop) {', @@ -655,7 +673,9 @@ var FRAG_SRC = [ 'vec4 distTex = texture2D(uTerrainDistTex, uv);', 'if (distTex.a > 0.5) {', 'float distNorm = (distTex.r * 65536.0 + distTex.g * 256.0 + distTex.b) / 16777215.0;', - 'tExit = min(tExit, distNorm * max(1.0, uFarPlane));', + 'float dist = distNorm * max(1.0, uFarPlane);', + 'if (dist < tEnter - 0.05) { gl_FragColor = vec4(0.0); return; }', + 'tExit = min(tExit, max(tEnter, dist));', '}', '}', 'tExit = min(tExit, tEnter + 30.0);', @@ -671,7 +691,7 @@ var FRAG_SRC = [ 'for (int i = 0; i < 24; i++) {', 'vec3 p = uCamPos + rd * t;', 'p += rd * (ign(gl_FragCoord.xy + vec2(float(i) * 7.13, float(i) * 3.71)) - 0.5) * stepSize * 0.25;', - 'float alt = max(0.0, length(p - C) - R);', + '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 d = cloudDensitySpherical(p, alt, baseThresh, soft);', @@ -683,7 +703,7 @@ var FRAG_SRC = [ 'vec3 ambC = albC * max(vec3(uSkyAmb), uStarAmb * vec3(0.7, 0.85, 1.0)) * 1.7;', 'vec3 moonC = albC * uMoonColor * (0.35 + 0.65 * max(0.0, dot(rd, uMoonDir))) * uMoonInt * 3.0;', 'vec3 cloudCol = direct + ambC + moonC;', - 'float alpha = clamp(d * stepSize * 2.20, 0.0, 1.0);', + 'float alpha = clamp(d * stepSize * 3.50, 0.0, 1.0);', 'cloudSum += cloudCol * alpha * trans;', 'trans *= (1.0 - alpha);', 'if (trans < 0.04) break;',