import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef } from 'react' import { useThree, useLoader } from '@react-three/fiber' import * as THREE from 'three' export interface EnvironmentMapHandle { setIntensity: (amount: number) => void } interface Props { panoUrl: string intensity: number } const BACKGROUND_BLURRINESS = 1 export const EnvironmentMap = forwardRef( function EnvironmentMap({ panoUrl, intensity }, ref) { const texture = useLoader(THREE.TextureLoader, panoUrl) const { scene } = useThree() const transitionAmountRef = useRef(1) const applyIntensity = useCallback(() => { const v = transitionAmountRef.current * intensity scene.environmentIntensity = v scene.backgroundIntensity = v }, [intensity, scene]) useEffect(() => { texture.mapping = THREE.EquirectangularReflectionMapping texture.colorSpace = THREE.SRGBColorSpace scene.environment = texture scene.background = texture scene.backgroundBlurriness = BACKGROUND_BLURRINESS scene.environmentRotation = new THREE.Euler(0, Math.PI / 2, 0) scene.backgroundRotation = new THREE.Euler(0, Math.PI / 2, 0) applyIntensity() return () => { if (scene.environment === texture) scene.environment = null if (scene.background === texture) scene.background = null } }, [texture, scene, applyIntensity]) useEffect(() => { applyIntensity() }, [applyIntensity]) useImperativeHandle(ref, () => ({ setIntensity: (amount: number) => { transitionAmountRef.current = amount applyIntensity() }, }), [applyIntensity]) return null }, )