clouds: repair curved deck entry and terrain occlusion

This commit is contained in:
Richard Zink committed 2026-10-12 14:45:31 +02:00
1 parent c546879b98
commit 624c2c6311
1 file changed
+29 -17
+29 -17
View File
@@ -241,6 +241,18 @@ var FRAG_SRC = [
'float sq = sqrt(disc);', 'float sq = sqrt(disc);',
'return vec2((-b - sq) / (2.0 * a), (-b + sq) / (2.0 * a));', 'return vec2((-b - sq) / (2.0 * a), (-b + sq) / (2.0 * a));',
'}', '}',
'float minPositiveRoot(vec2 r) {',
'float m = 1e9;',
'if (r.x > 0.0) m = min(m, r.x);',
'if (r.y > 0.0) m = min(m, r.y);',
'return m;',
'}',
'float maxPositiveRoot(vec2 r) {',
'float m = -1e9;',
'if (r.x > 0.0) m = max(m, r.x);',
'if (r.y > 0.0) m = max(m, r.y);',
'return m;',
'}',
// Two modes driven by uMode: // Two modes driven by uMode:
// 0 = SKY: full-screen pass that paints the sky gradient and // 0 = SKY: full-screen pass that paints the sky gradient and
// stars into the framebuffer (opaque, alpha = 1). // stars into the framebuffer (opaque, alpha = 1).
@@ -440,18 +452,10 @@ var FRAG_SRC = [
'float terrainY = terrElev(hp.xz) * uElevScale - earthDrop(hp.xz);', 'float terrainY = terrElev(hp.xz) * uElevScale - earthDrop(hp.xz);',
'float dh = terrainY - hp.y;', 'float dh = terrainY - hp.y;',
'if (abs(dh) < 0.02) break;', 'if (abs(dh) < 0.02) break;',
'tTerrain += dh / -rd.y;', 'tTerrain -= dh / -rd.y;',
'if (tTerrain < 0.1 || tTerrain > 90.0) { tTerrain = -1.0; break; }', 'if (tTerrain < 0.1 || tTerrain > 90.0) { tTerrain = -1.0; break; }',
'}', '}',
'}', '}',
// Cloud fully behind the terrain -> discard (framebuffer keeps
// the terrain color from the mesh pass).
'if (tTerrain > 0.0) {',
'vec2 topRoots = curvedLayerRoots(uCloudTop, ro, rd);',
'float tCloudTop = max(topRoots.x, topRoots.y);',
'if (tCloudTop > tTerrain) discard;',
'}',
// Cloud march. The output is the cloud's effective colour and // Cloud march. The output is the cloud's effective colour and
// coverage (alpha); the render pass uses alpha-blend so the // coverage (alpha); the render pass uses alpha-blend so the
// terrain mesh from the previous pass shows through transparent // terrain mesh from the previous pass shows through transparent
@@ -466,15 +470,23 @@ var FRAG_SRC = [
// have. // have.
'vec2 bot = curvedLayerRoots(uCloudBot, ro, rd);', 'vec2 bot = curvedLayerRoots(uCloudBot, ro, rd);',
'vec2 top = curvedLayerRoots(uCloudTop, ro, rd);', 'vec2 top = curvedLayerRoots(uCloudTop, ro, rd);',
'float tEnter = 1e9;',
'if (bot.x > 0.0) tEnter = min(tEnter, bot.x);',
'if (bot.y > 0.0) tEnter = min(tEnter, bot.y);',
'if (top.x > 0.0) tEnter = min(tEnter, top.x);',
'if (top.y > 0.0) tEnter = min(tEnter, top.y);',
'float tExit = max(max(bot.x, bot.y), max(top.x, top.y));',
'float roPy = ro.y + earthDrop(ro.xz);', 'float roPy = ro.y + earthDrop(ro.xz);',
'if (roPy >= uCloudBot && roPy <= uCloudTop) tEnter = 0.0;', 'float tEnter = 1e9;',
'if (tEnter > 1e8) { tEnter = 0.0; tExit = 14.0; }', '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);', 'if (tTerrain > 0.0) tExit = min(tExit, tTerrain);',
// A grazing ray would sample a path of well over a thousand km with // 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 // only 24 steps - coarse blobs along the horizon. Past this length