clouds: reduce raymarch jitter and high-frequency boiling

This commit is contained in:
Richard Zink committed 2026-10-12 14:53:57 +02:00
1 parent f25c7369cd
commit 8000c7be0e
1 file changed
+13 -13
+13 -13
View File
@@ -186,16 +186,16 @@ var FRAG_SRC = [
// The detail octave weighs at most 0.20 and fades to zero with // The detail octave weighs at most 0.20 and fades to zero with
// distance; past soft = 0.95 it contributes under 1 %, so the whole // distance; past soft = 0.95 it contributes under 1 %, so the whole
// 4-octave lookup is skipped for the (numerous) far samples. // 4-octave lookup is skipped for the (numerous) far samples.
'if (soft < 0.95) {', 'if (soft < 0.45) {',
'float d = fbm3(cp * 1.4 + vec3(uTime * 0.04, 7.3, uTime * 0.03));', 'float d = fbm3(cp * 1.15 + vec3(uTime * 0.04, 7.3, uTime * 0.03));',
'n = n + d * mix(0.20, 0.0, soft);', 'n = n + d * mix(0.12, 0.0, soft / 0.45);',
'}', '}',
// Cloud layer between uCloudBot and uCloudTop, densest in the // Cloud layer between uCloudBot and uCloudTop, densest in the
// middle (bell curve). The layer follows the Earth curvature. // middle (bell curve). The layer follows the Earth curvature.
'float h = clamp((py - uCloudBot) / (uCloudTop - uCloudBot), 0.0, 1.0);', 'float h = clamp((py - uCloudBot) / (uCloudTop - uCloudBot), 0.0, 1.0);',
'float profile = 4.0 * h * (1.0 - h); // bell curve', 'float profile = 4.0 * h * (1.0 - h); // bell curve',
'profile = max(profile, 0.0);', 'profile = max(profile, 0.0);',
'return smoothstep(baseThresh, baseThresh + 0.30 + soft * 0.25, n) * profile;', 'return smoothstep(baseThresh, baseThresh + 0.45 + soft * 0.35, n) * profile;',
'}', '}',
// Star field: project ray onto a far sphere, hash-grid for // Star field: project ray onto a far sphere, hash-grid for
// positions. Visible above the horizon at night with a small // positions. Visible above the horizon at night with a small
@@ -498,13 +498,13 @@ var FRAG_SRC = [
'float trans = 1.0;', 'float trans = 1.0;',
'for (int i = 0; i < 24; i++) {', 'for (int i = 0; i < 24; i++) {',
'vec3 p = ro + rd * t;', 'vec3 p = ro + rd * t;',
'p.y += (ign(gl_FragCoord.xy + vec2(float(i) * 7.13, float(i) * 3.71)) - 0.5) * stepSize;', '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);', 'float py = p.y + earthDrop(p.xz);',
'if (py > uCloudTop || py < uCloudBot - 0.1) break;', 'if (py > uCloudTop || py < uCloudBot - 0.1) break;',
'if (tTerrain > 0.0 && t >= tTerrain) break;', 'if (tTerrain > 0.0 && t >= tTerrain) break;',
'float cSoft = smoothstep(7.0, 20.0, t);', 'float cSoft = smoothstep(3.0, 14.0, t);',
'float d = cloudDensity(p, baseThresh, cSoft);', 'float d = cloudDensity(p, baseThresh, cSoft);',
'if (d > 0.005) {', 'if (d > 0.02) {',
'float lit = clamp((py - uCloudBot) / ((uCloudTop - uCloudBot) * 1.167), 0.0, 1.0);', 'float lit = clamp((py - uCloudBot) / ((uCloudTop - uCloudBot) * 1.167), 0.0, 1.0);',
'vec3 cloudCol;', 'vec3 cloudCol;',
'if (uPhysical > 0.5) {', 'if (uPhysical > 0.5) {',
@@ -537,7 +537,7 @@ var FRAG_SRC = [
'cloudCol = mix(uCloudShadow, uCloud, lit);', 'cloudCol = mix(uCloudShadow, uCloud, lit);',
'cloudCol = mix(cloudCol, uLight, max(0.15, uDayProgress) * 0.35 * lit);', 'cloudCol = mix(cloudCol, uLight, max(0.15, uDayProgress) * 0.35 * lit);',
'}', '}',
'float alpha = clamp(d * stepSize * 0.9, 0.0, 1.0);', 'float alpha = clamp(d * stepSize * 1.15, 0.0, 1.0);',
'cloudSum += cloudCol * alpha * trans;', 'cloudSum += cloudCol * alpha * trans;',
'trans *= (1.0 - alpha);', 'trans *= (1.0 - alpha);',
'if (trans < 0.04) break;', 'if (trans < 0.04) break;',
@@ -702,14 +702,14 @@ var CLOUD_SAMPLER_GLSL = [
// The detail octave weighs at most 0.20 and fades to zero with // The detail octave weighs at most 0.20 and fades to zero with
// distance; past soft = 0.95 it contributes under 1 %, so the whole // distance; past soft = 0.95 it contributes under 1 %, so the whole
// 4-octave lookup is skipped for the (numerous) far samples. // 4-octave lookup is skipped for the (numerous) far samples.
'if (soft < 0.95) {', 'if (soft < 0.45) {',
'float d = fbm3(cp * 1.4 + vec3(uTime * 0.04, 7.3, uTime * 0.03));', 'float d = fbm3(cp * 1.15 + vec3(uTime * 0.04, 7.3, uTime * 0.03));',
'n = n + d * mix(0.20, 0.0, soft);', 'n = n + d * mix(0.12, 0.0, soft / 0.45);',
'}', '}',
'float h = clamp((py - uCloudBot) / (uCloudTop - uCloudBot), 0.0, 1.0);', 'float h = clamp((py - uCloudBot) / (uCloudTop - uCloudBot), 0.0, 1.0);',
'float profile = 4.0 * h * (1.0 - h);', 'float profile = 4.0 * h * (1.0 - h);',
'profile = max(profile, 0.0);', 'profile = max(profile, 0.0);',
'return smoothstep(baseThresh, baseThresh + 0.30 + soft * 0.25, n) * profile;', 'return smoothstep(baseThresh, baseThresh + 0.45 + soft * 0.35, n) * profile;',
'}', '}',
].join('\n'); ].join('\n');
@@ -808,7 +808,7 @@ var TERRAIN_FRAG_SRC = [
'float dens = 0.0;', 'float dens = 0.0;',
'for (int ci = 0; ci < 5; ci++) {', 'for (int ci = 0; ci < 5; ci++) {',
'float tt = mix(tBot, tTop, (float(ci) + 0.5) / 5.0);', 'float tt = mix(tBot, tTop, (float(ci) + 0.5) / 5.0);',
'dens += cloudDensity(vWorld + uSunDir * tt, baseTh, smoothstep(7.0, 20.0, tt));', 'dens += cloudDensity(vWorld + uSunDir * tt, baseTh, smoothstep(3.0, 14.0, tt));',
'}', '}',
'cShadow = mix(uCloudShadowFloor, 1.0,', 'cShadow = mix(uCloudShadowFloor, 1.0,',
' exp(-dens * uCloudShadowDensity));', ' exp(-dens * uCloudShadowDensity));',