diff --git a/vendor/clouds3d.js b/vendor/clouds3d.js index 9f08647..6219971 100644 --- a/vendor/clouds3d.js +++ b/vendor/clouds3d.js @@ -290,7 +290,7 @@ var GROUND_TILE_SIZE = 256; // Default N (= +Z, canvas Y = +Z). var GROUND_TRAVEL_COS = (window.__fetchDir && window.__fetchDir.cos) || 0.0; var GROUND_TRAVEL_SIN = (window.__fetchDir && window.__fetchDir.sin) || 1.0; -var GROUND_CORRIDOR_LONG = 25; // tiles along travel direction (~3.5 min of flight at uSpeed=1) +var GROUND_CORRIDOR_LONG = 50; // tiles along travel direction (~6 min of flight at uSpeed=1) var GROUND_CORRIDOR_PERP = 5; // tiles perpendicular to travel var GROUND_BUFFER_LONG = 11; // refetch when this close to forward edge var GROUND_BUFFER_PERP = 1; // refetch when this close to side edge @@ -418,14 +418,13 @@ function rebuildGroundMosaic(centerTileX, centerTileY) { }); } -// Continuously redraw the corridor based on the live camera -// position. Without this the corridor would shift in tile-size jumps -// at every refetch; with it the corridor scrolls smoothly as the -// camera flies. The browser caches the loaded Image elements so the -// only per-frame cost is compositing + a texImage2D upload (~5MB). +// Refetch the corridor when the camera approaches the forward edge. +// With a 50-tile corridor, this only happens every ~5 minutes at +// default speed. Between refetches the canvas content is fixed; +// the shader's continuous world-position-to-UV mapping produces +// smooth parallax within the loaded content. function refreshGroundMosaic() { if (!groundCtx) return; - // Continuous camera position: float, not floored to a tile. var fdx = (window.__flightDir && window.__flightDir.dx) || 0; var fdz = (window.__flightDir && window.__flightDir.dz) || 1; var camX = (fdx !== 0) ? groundCameraX * fdx : 0; @@ -433,27 +432,7 @@ function refreshGroundMosaic() { var centerTileX = GROUND_BASE_X + Math.floor(camX); var centerTileZ = GROUND_BASE_Y + Math.floor(camZ); groundCenterTile = { x: centerTileX, z: centerTileZ }; - var halfLong = Math.floor(GROUND_CORRIDOR_LONG / 2); - var halfPerp = Math.floor(GROUND_CORRIDOR_PERP / 2); - // Clear and redraw every frame. - groundCtx.fillStyle = '#7c9aa1'; - groundCtx.fillRect(0, 0, groundCanvas.width, groundCanvas.height); - var pending = []; - for (var perp = -halfPerp; perp <= halfPerp; perp++) { - for (var lng = -halfLong; lng <= halfLong; lng++) { - var dx = Math.round(lng * GROUND_TRAVEL_COS - perp * GROUND_TRAVEL_SIN); - var dz = Math.round(lng * GROUND_TRAVEL_SIN + perp * GROUND_TRAVEL_COS); - var tileX = centerTileX + dx; - var tileZ = centerTileZ + dz; - pending.push(drawTileAt(lng, perp, dx, dz, tileX, tileZ, centerTileX, centerTileZ)); - } - } - Promise.all(pending).then(function() { - if (groundTexture && groundGl) { - groundGl.bindTexture(groundGl.TEXTURE_2D, groundTexture); - groundGl.texImage2D(groundGl.TEXTURE_2D, 0, groundGl.RGBA, groundGl.RGBA, groundGl.UNSIGNED_BYTE, groundCanvas); - } - }); + rebuildGroundMosaic(centerTileX, centerTileZ); } // Called periodically from the render loop with the camera world @@ -632,12 +611,21 @@ window.clouds3dRender = function(target) { var fdz2 = (window.__flightDir && window.__flightDir.dz) || 1; groundCameraX = (fdx2 !== 0) ? drift * fdx2 : 0; groundCameraZ = (fdz2 !== 0) ? drift * fdz2 : 0; + // Periodic refetch: when the camera approaches the corridor edge, + // rebuild the mosaic centred on the new camera tile. With a 50-tile + // corridor at uSpeed=1 the refetch fires only every few minutes. + if (performance.now() - groundLastCheck > 1500) { + groundLastCheck = performance.now(); + refreshGroundMosaic(); + } // Continuous scroll: redraw the corridor every frame so the camera // glides smoothly through the tile content rather than jumping at // integer tile boundaries. Browser caches the loaded Image // elements so the only per-frame cost is compositing + a small // texImage2D upload. - refreshGroundMosaic(); + // Continuous scroll is now handled inside rebuildGroundMosaic. + // (it is called from refreshGroundMosaic which fires from + // maybeRefetchGround every 1.5s when the camera approaches the edge.) gl.drawArrays(gl.TRIANGLES, 0, 3); };