diff --git a/vendor/clouds3d.js b/vendor/clouds3d.js index 3df1b66..e0f18d9 100644 --- a/vendor/clouds3d.js +++ b/vendor/clouds3d.js @@ -241,6 +241,18 @@ var FRAG_SRC = [ 'float sq = sqrt(disc);', '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: // 0 = SKY: full-screen pass that paints the sky gradient and // stars into the framebuffer (opaque, alpha = 1). @@ -440,18 +452,10 @@ var FRAG_SRC = [ 'float terrainY = terrElev(hp.xz) * uElevScale - earthDrop(hp.xz);', 'float dh = terrainY - hp.y;', '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; }', '}', '}', - // 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 // coverage (alpha); the render pass uses alpha-blend so the // terrain mesh from the previous pass shows through transparent @@ -466,15 +470,23 @@ var FRAG_SRC = [ // have. 'vec2 bot = curvedLayerRoots(uCloudBot, 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);', - 'if (roPy >= uCloudBot && roPy <= uCloudTop) tEnter = 0.0;', - 'if (tEnter > 1e8) { tEnter = 0.0; tExit = 14.0; }', + '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