Ground now uses real ray cast onto y=0 plane

Instead of mapping rd.x/rd.y to UV directly (which gave a flat
orthographic look), compute where the ray actually intersects
the ground plane and sample the satellite texture at that world
(x,z) coordinate. As the camera drifts forward (uTime), the
ground scrolls, giving the illusion of flight over real terrain.

- tGround = -ro.y / rd.y (with rd.y < 0 guard)
- gUv = (hitPoint.x, hitPoint.z) * 0.04 + 0.5
- Atmospheric perspective: ground fades toward sky with distance
  (fog starts at hit-distance 0, full at 30 world units)
- gmask 1.0 only when tGround > 0 (camera above ground AND ray
  pointing down), 0 otherwise
This commit is contained in:
Richard Zink committed 2026-10-07 20:40:46 +02:00
1 parent c9159a8876
commit 2ad51141c6
1 file changed
+13 -6
+13 -6
View File
@@ -195,13 +195,20 @@ var FRAG_SRC = [
// remain visible against a deep but not void-black sky.
'float skyDarkness = nightFactor * 0.55;',
'col = mix(col, col * (1.0 - skyDarkness), 1.0 - cloud);',
'// Horizon: when looking down (rd.y < 0), sample the satellite ground texture based on ray direction. Use the horizontal component as a UV \u2014 the further off-axis, the more the texture scrolls. Adds parallax-like feel even though the ground is a flat image.',
'float gmask = smoothstep(-0.02, -0.20, rd.y);',
'vec2 gUv = vec2(rd.x * 0.5 + 0.5, -rd.y * 0.5 + 0.3);',
'// Horizon: cast the ray onto the ground plane (y=0) and sample
// the satellite image at that world (x,z) coordinate. As
// the camera drifts forward over time the texture scrolls
// past, giving the illusion of flying over real terrain.
// Distant ground fades toward sky colour (atmospheric
// perspective).
'float tGround = (ro.y > 0.0 && rd.y < -0.001) ? -ro.y / rd.y : -1.0;',
'vec3 hitPoint = ro + rd * tGround;',
'vec2 gUv = vec2(hitPoint.x, hitPoint.z) * 0.04 + 0.5;',
'vec3 groundCol = texture2D(uGround, gUv).rgb;',
// Distance fog: distant ground fades toward sky colour.
'float fog = clamp(-rd.y * 1.5, 0.0, 1.0);',
'groundCol = mix(groundCol, uBg, fog * 0.6);',
'float fogAmount = clamp(tGround / 30.0, 0.0, 1.0);',
'groundCol = mix(groundCol, uBg, fogAmount * 0.75);',
// Ground mask: full ground when looking down, none when up.
'float gmask = (tGround > 0.0) ? smoothstep(0.0, -0.10, rd.y) : 0.0;',
'col = mix(col, groundCol, gmask);',
'gl_FragColor = vec4(col, 1.0);',
'}'