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

113 lines
3.8 KiB
TypeScript

import { useRef, useEffect } from "react";
import { useThree } from "@react-three/fiber";
import * as THREE from "three";
import {
useAzimuth,
useElevation,
useShadows,
useSunPosition,
useFloorItems,
useWallItems,
useTileDistance,
} 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();
const { planeValue } = useTileDistance();
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
/> */}
<planeGeometry args={[planeValue.width, planeValue.height]} />
<shadowMaterial
opacity={CONSTANTS.shadowConfig.shadowMaterialOpacity}
transparent
/>
</mesh>
</>
);
}