Reduce WebGL page texture runtime stalls
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
* Defines the canonical page geometry used by the WebGL book renderer.
|
||||
*/
|
||||
import { BaseModule } from './base-module.js';
|
||||
import { calculateProceduralBookThickness, snapProceduralPageCount } from './procedural-book-model.js?v=20260607-webgl-reveal-clock';
|
||||
import { calculateProceduralBookThickness, snapProceduralPageCount } from './procedural-book-model.js?v=20260607-webgl-resize-prime';
|
||||
|
||||
export const BOOK_TEXTURE_WIDTH = 3072;
|
||||
|
||||
|
||||
@@ -86,9 +86,6 @@ class BookTextureRendererModule extends BaseModule {
|
||||
this.currentSpread = spread || { left: [], right: [] };
|
||||
if (latestBlockId && Number(latestBlockId) > latestRenderedBlockId) {
|
||||
this.markPendingReveal(latestBlockId);
|
||||
const pendingSides = this.getBlockSides(latestBlockId);
|
||||
const immediateSides = ['left', 'right'].filter(side => !pendingSides.includes(side));
|
||||
if (immediateSides.length) this.drawSpread(this.currentSpread, immediateSides);
|
||||
return;
|
||||
}
|
||||
this.drawSpread(this.currentSpread);
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ const ModuleState = {
|
||||
ERROR: 'ERROR'
|
||||
};
|
||||
|
||||
const MODULE_CACHE_BUSTER = '20260607-webgl-reveal-clock';
|
||||
const MODULE_CACHE_BUSTER = '20260607-webgl-resize-prime';
|
||||
window.MODULE_CACHE_BUSTER = MODULE_CACHE_BUSTER;
|
||||
|
||||
/**
|
||||
|
||||
+31
-16
@@ -4,7 +4,7 @@ import { RenderPass } from 'https://esm.sh/three@0.165.0/examples/jsm/postproces
|
||||
import { SSAOPass } from 'https://esm.sh/three@0.165.0/examples/jsm/postprocessing/SSAOPass.js';
|
||||
import { SMAAPass } from 'https://esm.sh/three@0.165.0/examples/jsm/postprocessing/SMAAPass.js';
|
||||
import { OutputPass } from 'https://esm.sh/three@0.165.0/examples/jsm/postprocessing/OutputPass.js';
|
||||
import { PROCEDURAL_BOOK, createProceduralBookModel, snapProceduralPageCount } from './procedural-book-model.js?v=20260607-webgl-reveal-clock';
|
||||
import { PROCEDURAL_BOOK, createProceduralBookModel, snapProceduralPageCount } from './procedural-book-model.js?v=20260607-webgl-resize-prime';
|
||||
|
||||
const canvas = document.getElementById('scene');
|
||||
canvas.style.cursor = 'grab';
|
||||
@@ -55,6 +55,8 @@ const aoExcludedObjects = new Set();
|
||||
let renderedFrameCount = 0;
|
||||
let staticSceneBuffersDirty = true;
|
||||
let lastStaticCameraSignature = '';
|
||||
let lastResizeWidth = 0;
|
||||
let lastResizeHeight = 0;
|
||||
|
||||
function reportLabProgress(percent, message) {
|
||||
if (typeof appInitialState.reportProgress === 'function') {
|
||||
@@ -404,9 +406,11 @@ notifyBookPageCountChanged();
|
||||
await reportLabStep(82, 'Loading room reflection texture');
|
||||
await loadAiRoomReflection();
|
||||
await reportLabStep(86, 'Preparing static shadow and mirror maps');
|
||||
resize();
|
||||
primeSceneForLoader();
|
||||
await reportLabStep(90, 'Compiled WebGL scene passes');
|
||||
window.BookLabDebug = {
|
||||
cacheKey: window.MODULE_CACHE_BUSTER || null,
|
||||
textures: generatedTextureCanvases,
|
||||
ready: false,
|
||||
renderedFrames: 0,
|
||||
@@ -482,8 +486,8 @@ window.BookLabDebug = {
|
||||
return projectPointerToPage(clientX, clientY);
|
||||
},
|
||||
exportTexture(name) {
|
||||
if (name === 'left' || name === 'leftPage') return leftCanvas.toDataURL('image/png');
|
||||
if (name === 'right' || name === 'rightPage') return rightCanvas.toDataURL('image/png');
|
||||
if (name === 'left' || name === 'leftPage') return leftTexture.image?.toDataURL?.('image/png') || leftCanvas.toDataURL('image/png');
|
||||
if (name === 'right' || name === 'rightPage') return rightTexture.image?.toDataURL?.('image/png') || rightCanvas.toDataURL('image/png');
|
||||
return generatedTextureCanvases[name]?.toDataURL('image/png') || null;
|
||||
}
|
||||
};
|
||||
@@ -1675,17 +1679,14 @@ function handlePageCanvases(event) {
|
||||
}
|
||||
|
||||
function uploadPageTextureDirect(side, sourceCanvas) {
|
||||
const canvas = side === 'left' ? leftCanvas : rightCanvas;
|
||||
const texture = side === 'left' ? leftTexture : rightTexture;
|
||||
markPageTextureTiming('directUpload:start', { side });
|
||||
clearPageReveal(side, 'direct-upload');
|
||||
drawCanvasPageTexture(canvas, sourceCanvas, side);
|
||||
texture.needsUpdate = true;
|
||||
bindPageTextureSource(side, texture, sourceCanvas);
|
||||
markPageTextureTiming('directUpload:end', { side });
|
||||
}
|
||||
|
||||
function beginPageReveal(side, sourceCanvas, revealDetail = {}) {
|
||||
const canvas = side === 'left' ? leftCanvas : rightCanvas;
|
||||
const texture = side === 'left' ? leftTexture : rightTexture;
|
||||
const shader = getPageRevealShader(side);
|
||||
|
||||
@@ -1693,8 +1694,7 @@ function beginPageReveal(side, sourceCanvas, revealDetail = {}) {
|
||||
side,
|
||||
wordCount: Array.isArray(revealDetail.wordRects) ? revealDetail.wordRects.length : 0
|
||||
});
|
||||
drawCanvasPageTexture(canvas, sourceCanvas, side);
|
||||
texture.needsUpdate = true;
|
||||
bindPageTextureSource(side, texture, sourceCanvas);
|
||||
|
||||
pageRevealState[side] = {
|
||||
startedAt: revealDetail.startNow ? performance.now() : null,
|
||||
@@ -1875,12 +1875,21 @@ function updatePageRevealAnimations(now) {
|
||||
});
|
||||
}
|
||||
|
||||
function drawCanvasPageTexture(canvas, sourceCanvas, side) {
|
||||
markPageTextureTiming('drawCanvasPageTexture:start', {
|
||||
function bindPageTextureSource(side, texture, sourceCanvas) {
|
||||
const fallbackCanvas = side === 'left' ? leftCanvas : rightCanvas;
|
||||
const nextCanvas = sourceCanvas || fallbackCanvas;
|
||||
markPageTextureTiming('bindPageTextureSource:start', {
|
||||
side,
|
||||
width: canvas?.width || 0,
|
||||
height: canvas?.height || 0
|
||||
width: nextCanvas?.width || 0,
|
||||
height: nextCanvas?.height || 0
|
||||
});
|
||||
texture.image = sourceCanvas || fallbackCanvas;
|
||||
texture.needsUpdate = true;
|
||||
updatePageTextureDebugState(side, nextCanvas, sourceCanvas, true);
|
||||
markPageTextureTiming('bindPageTextureSource:end', { side });
|
||||
}
|
||||
|
||||
function drawCanvasPageTexture(canvas, sourceCanvas, side) {
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.fillStyle = '#f2ead0';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
@@ -1894,7 +1903,6 @@ function drawCanvasPageTexture(canvas, sourceCanvas, side) {
|
||||
|
||||
ctx.drawImage(sourceCanvas, 0, 0, canvas.width, canvas.height);
|
||||
updatePageTextureDebugState(side, canvas, sourceCanvas, true);
|
||||
markPageTextureTiming('drawCanvasPageTexture:end', { side });
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1916,11 +1924,15 @@ function updatePageTextureDebugState(side, canvas, source, painted) {
|
||||
height: canvas.height,
|
||||
sourceId: source?.id || 'book-texture-renderer',
|
||||
sourceTextLength: 0,
|
||||
darkPixels: countPageTextureDarkPixels(canvas)
|
||||
darkPixels: shouldSamplePageTextureDebug() ? countPageTextureDarkPixels(canvas) : null
|
||||
};
|
||||
document.documentElement.dataset.webglPageTextures = JSON.stringify(state);
|
||||
}
|
||||
|
||||
function shouldSamplePageTextureDebug() {
|
||||
return tableDebugMode !== tableDebugModes.none;
|
||||
}
|
||||
|
||||
function countPageTextureDarkPixels(canvas) {
|
||||
const sampleCanvas = document.createElement('canvas');
|
||||
const sampleSize = 64;
|
||||
@@ -2987,9 +2999,12 @@ function tintAmbientFromCanvas(canvas) {
|
||||
}
|
||||
|
||||
function resize() {
|
||||
markStaticSceneBuffersDirty();
|
||||
const width = Math.max(1, window.innerWidth);
|
||||
const height = Math.max(1, window.innerHeight);
|
||||
const sizeChanged = width !== lastResizeWidth || height !== lastResizeHeight;
|
||||
lastResizeWidth = width;
|
||||
lastResizeHeight = height;
|
||||
if (sizeChanged) markStaticSceneBuffersDirty();
|
||||
renderer.setSize(width, height, false);
|
||||
if (composer) composer.setSize(width, height);
|
||||
if (sceneAoPass) sceneAoPass.setSize(width, height);
|
||||
|
||||
Reference in New Issue
Block a user