From e4eb4a81b2a283f70b19f749e3863440aed5c999 Mon Sep 17 00:00:00 2001 From: tuyenio Date: Wed, 24 Jun 2026 16:14:49 +0700 Subject: [PATCH] =?UTF-8?q?perf:=20=E1=BA=A3nh=20m=E1=BB=9D=20blur-up=20(L?= =?UTF-8?q?QIP)=20khi=20t=E1=BA=A3i=20c=E1=BA=A3nh?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- src/app/components/VirtualTour.tsx | 32 ++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/app/components/VirtualTour.tsx b/src/app/components/VirtualTour.tsx index 0427bf0..bf7cf74 100644 --- a/src/app/components/VirtualTour.tsx +++ b/src/app/components/VirtualTour.tsx @@ -27,6 +27,7 @@ import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js"; import Lottie, { type LottieRefCurrentProps } from "lottie-react"; import letterAnimation from "@/letter.json"; import { chuaThaiLacTour } from "@/app/tours/chua-thai-lac"; +import { lqip } from "@/app/tours/chua-thai-lac.lqip"; type SceneId = string; @@ -193,6 +194,23 @@ const defaultTourConfig = chuaThaiLacTourConfig; const getTourConfig = (tourId?: string) => toursById[tourId ?? ""] ?? defaultTourConfig; +// Texture ảnh mờ (blur-up) tạo từ data-URI base64 — hiện gần như tức thì khi cảnh đang tải. +const lqipTextureCache = new Map(); +function loadLqipTexture(image: string) { + const data = lqip[image]; + if (!data) { + return null; + } + const cached = lqipTextureCache.get(image); + if (cached) { + return cached; + } + const texture = new THREE.TextureLoader().load(data); + texture.colorSpace = THREE.SRGBColorSpace; + lqipTextureCache.set(image, texture); + return texture; +} + const panoramaTextureCache = new Map(); const panoramaTexturePromises = new Map>(); const panoramaTextureProgress = new Map(); @@ -1635,6 +1653,11 @@ function TourExperience({ if (cachedTexture) { prepareTransitionTexture(cachedTexture); } else { + const lqipTexture = loadLqipTexture(scene.image); + if (lqipTexture) { + transitionMaterial.map = lqipTexture; + transitionMaterial.needsUpdate = true; + } loadPanoramaTexture(scene.image, (progress) => { if (transitionTokenRef.current === token) { setLoadProgress(progress); @@ -1747,6 +1770,15 @@ function TourExperience({ setIsLoading(!initialCachedTexture); setLoadProgress(initialCachedTexture ? 100 : 0); + if (!initialCachedTexture) { + const lqipTexture = loadLqipTexture(scene.image); + if (lqipTexture) { + material.map = lqipTexture; + material.opacity = 1; + material.needsUpdate = true; + needsRenderRef.current = true; + } + } loadTexture .then((texture) => { if (transitionTokenRef.current !== token) return;