From a06f7038d8216bd571caec024ac29c49eba124cf Mon Sep 17 00:00:00 2001 From: Richard Zink Date: Mon, 12 Oct 2026 15:13:26 +0200 Subject: [PATCH] atmosphere: make Rayleigh sky follow spherical Earth radius --- vendor/clouds3d.js | 51 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/vendor/clouds3d.js b/vendor/clouds3d.js index 51c3595..2860b80 100644 --- a/vendor/clouds3d.js +++ b/vendor/clouds3d.js @@ -257,6 +257,51 @@ var FRAG_SRC = [ 'if (r.y > 0.0) m = max(m, r.y);', 'return m;', '}', + 'vec3 sphericalRayleighTau(vec3 rd) {', + 'if (uCurvatureOn < 0.5) {', + 'float viewY = max(rd.y, 0.0);', + 'float mView = (viewY > 0.02) ? min(38.0, 1.0 / viewY) : 38.0;', + 'return uRayleighBeta * mView;', + '}', + 'float R = max(1.0, uEarthRadius);', + 'float H = max(1.0, uAtmoHeightUnits);', + 'float Hs = max(0.05, uAtmoScaleHeightUnits);', + 'vec3 C = vec3(uCamPos.x, -R, uCamPos.z);', + 'vec3 oc = uCamPos - C;', + 'float b = dot(oc, rd);', + 'float rOut = R + H;', + 'float cOut = dot(oc, oc) - rOut * rOut;', + 'float tStart = 0.0;', + 'float tEnd = 100.0;', + 'float discOut = b * b - cOut;', + 'if (discOut > 0.0) {', + 'float sq = sqrt(discOut);', + 'float t1 = -b - sq;', + 'float t2 = -b + sq;', + 'if (cOut > 0.0) tStart = max(0.0, t1);', + 'tEnd = max(0.0, t2);', + '}', + 'float cIn = dot(oc, oc) - R * R;', + 'float discIn = b * b - cIn;', + 'if (discIn > 0.0) {', + 'float sq = sqrt(discIn);', + 'float t1 = -b - sq;', + 'float t2 = -b + sq;', + 'if (t1 > 0.0) tEnd = min(tEnd, t1);', + 'else if (t2 > 0.0) tEnd = min(tEnd, t2);', + '}', + 'if (tEnd <= tStart) return vec3(0.0);', + 'float step = (tEnd - tStart) / 16.0;', + 'float t = tStart + step * 0.5;', + 'float column = 0.0;', + 'for (int i = 0; i < 16; i++) {', + 'vec3 p = uCamPos + rd * t;', + 'float alt = max(0.0, length(p - C) - R);', + 'column += exp(-alt / Hs) * step / Hs;', + 't += step;', + '}', + 'return uRayleighBeta * column;', + '}', // Two modes driven by uMode: // 0 = SKY: full-screen pass that paints the sky gradient and // stars into the framebuffer (opaque, alpha = 1). @@ -345,9 +390,7 @@ var FRAG_SRC = [ 'float phase = 0.5 + 0.5 * cosT * cosT;', 'float sunUp = smoothstep(-0.25, 0.05, uSunAlt);', 'vec3 sunTop = uSunColor * uSunInt * sunUp;', - 'float viewY = max(rd.y, 0.0);', - 'float mView = (viewY > 0.02) ? min(38.0, 1.0 / viewY) : 38.0;', - 'vec3 tauView = uRayleighBeta * mView;', + 'vec3 tauView = sphericalRayleighTau(rd);', 'vec3 single = phase * sunTop * (1.0 - exp(-tauView));', 'vec3 multi = phase * sunTop * tauView * tauView * 0.12;', 'vec3 ambient = max(vec3(uSkyAmb), uStarAmb * vec3(0.7, 0.85, 1.0)) *', @@ -5661,6 +5704,8 @@ window.clouds3dRender = function(target) { gl.enableVertexAttribArray(s.aPos); gl.vertexAttribPointer(s.aPos, 2, gl.FLOAT, false, 0, 0); gl.uniformMatrix4fv(s.uViewProjInv, false, viewProjInv); + gl.uniform3f(s.uCamPos, camX, camY, camZ); + gl.uniform1f(s.uCurvatureOn, CURVATURE_ON ? 1.0 : 0.0); gl.disable(gl.DEPTH_TEST); gl.depthMask(false); gl.uniform1i(s.uMode, 0);