From 4cf3c00dfacafde84a0c3d8e152b7a593b5cf13d Mon Sep 17 00:00:00 2001 From: Richard Zink Date: Thu, 8 Oct 2026 07:23:14 +0200 Subject: [PATCH] Partial refetch: only draw new tiles, don't clear canvas With BUFFER_LONG = 1, refetch fires every ~1 tile of motion (every ~8 sec at default speed). With BUFFER = 1 the center shifts by ~1 tile per refetch, so only ~1 net new tile needs fetching each time (the one at the very front of the new corridor). Switch to partial refetch: - Don't clear the canvas before redrawing - Skip tiles already in groundLoadedTiles (they're still on the canvas at the right position from a prior refetch) - Only newly-positioned tiles are drawn (the ones in the new front of the corridor, ahead in flight direction) Effect: user sees tiles appearing at the front of the corridor in the direction of travel, not the whole canvas flashing every 8 sec. With N flight, fetch activity shows up at the top of the screen (where lng=+12 lands after the axis swap), confirming the flight direction is correct. --- vendor/clouds3d.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/vendor/clouds3d.js b/vendor/clouds3d.js index b714de2..ec2142a 100644 --- a/vendor/clouds3d.js +++ b/vendor/clouds3d.js @@ -379,12 +379,12 @@ 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 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); + // Partial refetch: don't clear the canvas. Tiles already loaded + // (from a previous refetch) stay visible. Only new tiles are + // drawn on top, so fetch activity shows up at the front of the + // corridor (in flight direction) instead of flashing the whole + // canvas. The drawTileAt call hashes by (tileX, tileY) so already- + // loaded tiles are skipped. var promises = []; for (var perp = -halfPerp; perp <= halfPerp; perp++) { for (var lng = -halfLong; lng <= halfLong; lng++) { @@ -393,6 +393,11 @@ function rebuildGroundMosaic(centerTileX, centerTileY) { // camera's actual path, not just the +X axis. 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 tileY = centerTileY + dz; + // Skip tiles already loaded (still drawn at the right canvas + // position from a previous refetch or the initial load). + if (groundLoadedTiles[tileX + '_' + tileY]) continue; promises.push(drawTileAt(lng, perp, dx, dz, centerTileX, centerTileY)); } }