diff --git a/vendor/clouds3d.js b/vendor/clouds3d.js index 16f08f4..3ff7a54 100644 --- a/vendor/clouds3d.js +++ b/vendor/clouds3d.js @@ -206,9 +206,15 @@ var FRAG_SRC = [ 'vec2 offset = vec2(hitPoint.x, hitPoint.z) - uGroundCenter;', 'vec2 rotated = vec2(offset.x * 0.0 + offset.y * 1.0, -offset.x * 1.0 + offset.y * 0.0);', 'vec2 gUv = rotated / uGroundSize + 0.5;', + // Soft fade at UV edges so OOB samples blend to fog instead of producing a hard stripe. + 'float perpFade = smoothstep(-0.08, 0.05, gUv.y) * smoothstep(1.08, 0.95, gUv.y);', + 'float longFade = smoothstep(-0.08, 0.05, gUv.x) * smoothstep(1.08, 0.95, gUv.x);', + 'float edgeFade = perpFade * longFade;', 'vec3 groundCol = texture2D(uGround, gUv).rgb;', 'float fogAmount = clamp(tGround / 14.0, 0.0, 1.0);', 'groundCol = mix(groundCol, uBg, fogAmount);', + // Edge fade: ground smoothly disappears near canvas boundary. + 'groundCol = mix(uBg, groundCol, edgeFade);', // 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);', @@ -277,7 +283,7 @@ var GROUND_TRAVEL_COS = 0.0; // cos(90 deg) var GROUND_TRAVEL_SIN = 1.0; // sin(90 deg) var GROUND_CORRIDOR_LONG = 25; // tiles along travel direction (~3.5 min of flight at uSpeed=1) var GROUND_CORRIDOR_PERP = 5; // tiles perpendicular to travel -var GROUND_BUFFER_LONG = 3; // refetch when this close to forward edge +var GROUND_BUFFER_LONG = 1; // refetch when this close to forward edge var GROUND_BUFFER_PERP = 1; // refetch when this close to side edge // Passau tile at zoom 11 var GROUND_BASE_X = 1099; @@ -336,13 +342,13 @@ function rebuildGroundMosaic(centerTileX, centerTileY) { groundCenterTile = { x: centerTileX, y: centerTileY }; var halfLong = Math.floor(GROUND_CORRIDOR_LONG / 2); var halfPerp = Math.floor(GROUND_CORRIDOR_PERP / 2); - // Clear with fog colour so the texture is never undefined + // Clear with fog colour so we don't get ghosting from old tiles + // at wrong canvas positions. The shader's edgeFade makes OOB + // samples blend smoothly to uBg, so the brief fog state during + // tile fetch is invisible. groundCtx.fillStyle = '#7c9aa1'; groundCtx.fillRect(0, 0, groundCanvas.width, groundCanvas.height); var promises = []; - // Iterate the corridor in its own rotated frame (long, perp), - // then map each (long, perp) to a world tile via rotation and to - // a canvas pixel via the iteration indices. for (var perp = -halfPerp; perp <= halfPerp; perp++) { for (var lng = -halfLong; lng <= halfLong; lng++) { // Tile offset from camera in world (tile) coords, rotated