diff --git a/src/pages/page.tsx b/src/pages/page.tsx index 8196054..e4dcd72 100644 --- a/src/pages/page.tsx +++ b/src/pages/page.tsx @@ -96,9 +96,16 @@ export function HomePage(): React.JSX.Element | null { gl.shadowMap.type = THREE.PCFShadowMap; gl.shadowMap.autoUpdate = true; + // The browser hands us a WEBGL_lose_context extension we can use to + // ask the GPU to restore the context after a loss. Without this the + // page stays frozen on a black canvas until the user reloads. + const loseContextExt = gl.getContext().getExtension("WEBGL_lose_context"); + const handleContextLost = (event: Event) => { event.preventDefault(); - logger.error("WebGL", "Context lost - GPU resources exhausted"); + logger.error("WebGL", "Context lost - attempting auto-restore"); + // Give the GPU a moment to free resources before asking it back. + window.setTimeout(() => loseContextExt?.restoreContext(), 500); }; const handleContextRestored = () => { @@ -121,10 +128,14 @@ export function HomePage(): React.JSX.Element | null { // all hooks (rules of hooks) but BEFORE any expensive render. if (!hasSiteBeenVisitedToday()) return null; + const showFadeToVideoOverlay = + introStep === "fade-to-video" || + (introStep === "loading-map" && sceneLoadingState.status === "ready"); + const renderIntroOverlay = () => { + if (showFadeToVideoOverlay) return ; + switch (introStep) { - case "fade-to-video": - return ; case "video": return ; case "dialogue-intro":