Dwinzo_dev/app/src/modules/scene/environment/shadow.tsx

84 lines
3.4 KiB
TypeScript
Raw Normal View History

2025-03-25 12:04:20 +00:00
import { useRef, useEffect} from 'react';
import { useThree } from '@react-three/fiber';
import * as THREE from 'three';
import { useAzimuth, useElevation, useShadows, useSunPosition, useFloorItems, useWallItems } from '../../../store/store';
import * as CONSTANTS from '../../../types/world/worldConstants';
const shadowWorker = new Worker(new URL('../../../services/factoryBuilder/webWorkers/shadowWorker', import.meta.url));
export default function Shadows() {
const { shadows, setShadows } = useShadows();
const { sunPosition, setSunPosition } = useSunPosition();
const lightRef = useRef<THREE.DirectionalLight | null>(null);
const targetRef = useRef<THREE.Object3D | null>(null);
const { controls, gl } = useThree();
const { elevation, setElevation } = useElevation();
const { azimuth, setAzimuth } = useAzimuth();
const { floorItems } = useFloorItems();
const { wallItems } = useWallItems();
useEffect(() => {
gl.shadowMap.enabled = true;
gl.shadowMap.type = THREE.PCFShadowMap;
}, [gl, floorItems, wallItems]);
useEffect(() => {
if (lightRef.current && targetRef.current) {
lightRef.current.target = targetRef.current;
}
}, []);
useEffect(() => {
shadowWorker.onmessage = (event) => {
const { lightPosition, controlsTarget } = event.data;
if (lightRef.current && targetRef.current && controls) {
lightRef.current.position.copy(lightPosition);
targetRef.current.position.copy(controlsTarget);
}
};
}, [shadowWorker, controls]);
const updateShadows = () => {
if (controls && shadowWorker) {
const offsetDistance = CONSTANTS.shadowConfig.shadowOffset;
const controlsTarget = (controls as any).getTarget();
shadowWorker.postMessage({ controlsTarget, sunPosition, offsetDistance });
}
};
useEffect(() => {
if (controls && shadows) {
updateShadows();
(controls as any).addEventListener('update', updateShadows);
return () => {
(controls as any).removeEventListener('update', updateShadows);
};
}
}, [controls, elevation, azimuth, shadows]);
return (
<>
{/* {(lightRef.current?.shadow) &&
<cameraHelper visible={shadows} args={[lightRef.current.shadow.camera]} />
} */}
<directionalLight
ref={lightRef}
castShadow={shadows}
shadow-mapSize-width={CONSTANTS.shadowConfig.shadowmapSizewidth}
shadow-mapSize-height={CONSTANTS.shadowConfig.shadowmapSizeheight}
shadow-camera-far={CONSTANTS.shadowConfig.shadowcamerafar}
shadow-camera-near={CONSTANTS.shadowConfig.shadowcameranear}
shadow-camera-top={CONSTANTS.shadowConfig.shadowcameratop}
shadow-camera-bottom={CONSTANTS.shadowConfig.shadowcamerabottom}
shadow-camera-left={CONSTANTS.shadowConfig.shadowcameraleft}
shadow-camera-right={CONSTANTS.shadowConfig.shadowcameraright}
shadow-bias={CONSTANTS.shadowConfig.shadowbias}
shadow-normalBias={CONSTANTS.shadowConfig.shadownormalBias}
/>
<object3D ref={targetRef} />
<mesh position={CONSTANTS.shadowConfig.shadowMaterialPosition} rotation={CONSTANTS.shadowConfig.shadowMaterialRotation} receiveShadow>
<planeGeometry args={[CONSTANTS.planeConfig.width, CONSTANTS.planeConfig.height]} />
<shadowMaterial opacity={CONSTANTS.shadowConfig.shadowMaterialOpacity} transparent />
</mesh>
</>
);
}