clouds: remove old cloud raymarch shader pass

This commit is contained in:
Richard Zink committed 2026-10-12 15:00:08 +02:00
1 parent 20b47f5460
commit 06fb2f8d8f
1 file changed
+1 -138
+1 -138
View File
@@ -439,124 +439,7 @@ var FRAG_SRC = [
'return;',
'}',
// ---- CLOUDS pass ----
// Ray-terrain intersection (used to discard clouds that are
// entirely behind the terrain mesh).
'vec2 terrRoots = curvedLayerRoots(0.0, ro, rd);',
'float tTerrain = -1.0;',
'if (terrRoots.x > 0.0) tTerrain = terrRoots.x;',
'else if (terrRoots.y > 0.0) tTerrain = terrRoots.y;',
// Keep cloud occlusion on the curved Earth horizon only. Detailed
// terrain-height clipping made the deck boil and cut holes.
'if (tTerrain < 0.1) tTerrain = -1.0;',
// Cloud march. The output is the cloud's effective colour and
// coverage (alpha); the render pass uses alpha-blend so the
// terrain mesh from the previous pass shows through transparent
// cloud pixels.
'float baseThresh = mix(0.72, 0.40, uDensity);',
// March the deck in HEIGHT, not along the ray. Sampling a slab along
// the ray gives every view angle its own set of sample heights, and
// those sets line up across the screen as bands - exactly the stacked
// slabs this looked like. Walking the layer from its own top to its
// own bottom and weighting each step by its path length is independent
// of the view angle, and grazing rays get the long path they really
// have.
'vec2 bot = curvedLayerRoots(uCloudBot, ro, rd);',
'vec2 top = curvedLayerRoots(uCloudTop, ro, rd);',
'float roPy = ro.y + earthDrop(ro.xz);',
'float tEnter = 1e9;',
'float tExit = -1e9;',
'if (roPy >= uCloudBot && roPy <= uCloudTop) {',
'tEnter = 0.0;',
'tExit = max(maxPositiveRoot(bot), maxPositiveRoot(top));',
'} else if (roPy > uCloudTop) {',
'tEnter = minPositiveRoot(top);',
'tExit = maxPositiveRoot(bot);',
'if (tExit < 0.0) tExit = maxPositiveRoot(top);',
'} else {',
'tEnter = minPositiveRoot(bot);',
'tExit = maxPositiveRoot(top);',
'if (tExit < 0.0) tExit = maxPositiveRoot(bot);',
'}',
'if (tEnter > 1e8 || tExit <= tEnter) { tEnter = 0.0; tExit = 14.0; }',
'if (tTerrain > 0.0 && tEnter > tTerrain) discard;',
'if (tTerrain > 0.0) tExit = min(tExit, tTerrain);',
// A grazing ray would sample a path of well over a thousand km with
// only 24 steps - coarse blobs along the horizon. Past this length
// the deck is inside the haze anyway, so the march stops there.
'tExit = min(tExit, tEnter + 18.0);',
'float stepSize = max(0.0, (tExit - tEnter) / 24.0);',
'float t = tEnter + stepSize * (0.5 + ign(gl_FragCoord.xy));',
'vec3 cloudSum = vec3(0.0);',
'float trans = 1.0;',
'for (int i = 0; i < 24; i++) {',
'vec3 p = ro + rd * t;',
'p.y += (ign(gl_FragCoord.xy + vec2(float(i) * 7.13, float(i) * 3.71)) - 0.5) * stepSize * 0.35;',
'float py = p.y + earthDrop(p.xz);',
'if (py > uCloudTop || py < uCloudBot - 0.1) break;',
'if (tTerrain > 0.0 && t >= tTerrain) break;',
'float cSoft = smoothstep(4.0, 18.0, t);',
'float d = cloudDensity(p, baseThresh, cSoft);',
'if (d > 0.02) {',
'float lit = clamp((py - uCloudBot) / ((uCloudTop - uCloudBot) * 1.167), 0.0, 1.0);',
'vec3 cloudCol;',
'if (uPhysical > 0.5) {',
// The night palette colours are already darkened for
// night, and multiplying them by the night light would
// double-darken into invisibility. Physical mode
// therefore uses a brightness-normalised albedo (theme
// hue kept, brightness from the light model) and lets
// the vertical gradient act as a shading ramp.
'vec3 albC = uCloudAlbedo * mix(0.78, 1.0, lit);',
// Self-shading: probe the density towards the sun, so
// thick cloud interior stays dark and thin edges light up.
// d > 0.85 already clamps selfLit to its floor, so the
// second density lookup (a whole fbm) is skipped there.
'float thick = (d > 0.85) ? 1.0 :',
'cloudDensity(p + uSunDir * 2.2, baseThresh, cSoft);',
'float selfLit = clamp(1.0 - thick * 1.3, 0.12, 1.0);',
// Forward scattering - clouds brighten towards the sun
// (silver lining) instead of a flat day/night ramp.
'float cosT = dot(rd, -uSunDir);',
'float phase = 0.30 + 0.70 * pow(max(0.0, cosT), 2.5);',
'vec3 direct = albC * uSunColor * phase * uSunInt * selfLit;',
// A cloud deck is a bright, thick scatterer: it catches
// the whole diffuse column (skylight, starlight) and
// stands clearly above the dark sky at night.
'vec3 ambC = albC * max(vec3(uSkyAmb), uStarAmb * vec3(0.75, 0.85, 1.0)) * 1.7;',
'vec3 moonC = albC * uMoonColor * (0.35 + 0.65 * max(0.0, dot(rd, uMoonDir))) * uMoonInt * 3.0;',
'cloudCol = direct + ambC + moonC;',
'} else {',
'cloudCol = mix(uCloudShadow, uCloud, lit);',
'cloudCol = mix(cloudCol, uLight, max(0.15, uDayProgress) * 0.35 * lit);',
'}',
'float alpha = clamp(d * stepSize * 1.30, 0.0, 1.0);',
'cloudSum += cloudCol * alpha * trans;',
'trans *= (1.0 - alpha);',
'if (trans < 0.04) break;',
'}',
't += stepSize;',
'}',
'float cloudAlpha = 1.0 - trans;',
'vec3 cloudColor = (cloudAlpha > 0.001) ? cloudSum / cloudAlpha : vec3(0.0);',
// Aerial perspective for the deck too: a distant cloud is seen
// through its own air column, so it dissolves into the same airlight
// the ground fades into. Without it the far clouds keep full contrast
// and the horizon reads as stacked bands.
// A cloud at 12 km looks through far less air than the ground at the
// horizon, so this uses its own much smaller factor, a desaturated
// haze colour (not the saturated blue) and a hard cap: distant cloud
// loses contrast, it does not turn blue.
'if (uPhysical > 0.5 && cloudAlpha > 0.001) {',
'float cTau = uAirDensity * min(tExit, 60.0) * uCloudHaze;',
'float cHaze = min(0.55, 1.0 - exp(-cTau));',
'vec3 airAvg = vec3(dot(uAirColor, vec3(0.3333)));',
'vec3 hazeCol = mix(uAirColor, airAvg, 0.55);',
'float cosTA = dot(rd, uSunDir);',
'float phaseA = 0.5 + 0.5 * cosTA * cosTA;',
'cloudColor = mix(cloudColor, hazeCol * phaseA, cHaze);',
'}',
'gl_FragColor = vec4(cloudColor, cloudAlpha);',
'if (uMode == 1) { gl_FragColor = vec4(0.0); return; }',
'}'
].join('\n');
@@ -6389,26 +6272,6 @@ window.clouds3dRender = function(target) {
}
}
// ---- Cloud pass (uMode = 1) --------------------------------------
// Alpha-blend over the framebuffer (terrain mesh + sky+stars).
// Depth test/write OFF — the manual discard in the cloud shader
// (tCloudTop > tTerrain) handles cloud-behind-mesh occlusion, and
// the depth values from the full-screen quad would only confuse the
// alpha blend.
gl.useProgram(s.prog);
gl.bindBuffer(gl.ARRAY_BUFFER, s.buf);
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.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.uniform1i(s.uMode, 1);
gl.drawArrays(gl.TRIANGLES, 0, 3);
if (ATMO_MODEL_ON) {
gl.uniform1i(s.uMode, 2);
gl.drawArrays(gl.TRIANGLES, 0, 3);