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;