Bigger corridor + refetch-based continuous scroll
The per-frame redraw caused texImage2D upload of 8MB every frame, which the browser couldn't keep up with -> tiles disappeared. Reverted to refetch-based updates but with two key changes: - Corridor 25 -> 50 tiles long (~6 min of flight at uSpeed=1 before refetch) - Tiles redraw with fractional camera position, so the corridor tracks the camera smoothly within the loaded content The 50-tile corridor covers enough flight time that refetches happen rarely (~6 min), but the camera's continuous position is still reflected in the mosaic's center. So between refetches the visible content scrolls smoothly.
This commit is contained in:
1 parent
4f8fd4b62a
commit
91ff8fb9d7
1 file changed
+17
-29
Vendored
+17
-29
@@ -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);
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user