Hi all,
I am relatively new to three.js and I am having trouble lighting a 3D earth properly. I would like to have a single light source that resembles the sun in the distance and when I rotate the earth the sunlight stays static. This is to make it look realistic as it does in real life. I am having issues with the light not illuminating my 3D earth model. I have confirmed that with other simple lighting schemes, my earth model does illuminate.
Any help or guidance would be greatly appreciated!
import React, { Suspense, useEffect, useState, useRef } from "react";
import { Canvas, useThree } from "@react-three/fiber";
import { OrbitControls, Preload, useGLTF } from "@react-three/drei";
import * as THREE from 'three';
import CanvasLoader from '../Loader';
const Earth = ({ isMobile }) => {
const earth = useGLTF("./earth/earth.gltf");
return (
<primitive
object={earth.scene}
scale={isMobile ? 0.7 : 5}
position={isMobile ? [0, -1, -1.5] : [0, -3.5, 0]}
rotation={[0, 0, 0]}
/>
);
}
const FixedSpotlight = () => {
const { scene } = useThree();
useEffect(() => {
const spotLight = new THREE.SpotLight(0xffffff, 2, 100, Math.PI / 4, 0.2);
spotLight.position.set(20, 20, 20);
const lightTarget = new THREE.Object3D();
lightTarget.position.set(0, 0, 0);
scene.add(lightTarget);
spotLight.target = lightTarget;
scene.add(spotLight);
return () => {
scene.remove(spotLight);
scene.remove(lightTarget);
};
}, [scene]);
return null;
}
const EarthCanvas = () => {
const [isMobile, setIsMobile] = useState(false);
useEffect(() => {
const mediaQuery = window.matchMedia('(max-width: 500px)');
setIsMobile(mediaQuery.matches);
const handleMediaQueryChange = (event) => {
setIsMobile(event.matches);
}
mediaQuery.addEventListener('change', handleMediaQueryChange);
return () => {
mediaQuery.removeEventListener('change', handleMediaQueryChange);
};
}, []);
return (
<Canvas
frameloop="demand"
shadows
camera={{ position: [55, 0, 0], fov: 25}}
gl={{ preserveDrawingBuffer: true }}
>
<FixedSpotlight />
<Suspense fallback={<CanvasLoader />}>
<OrbitControls
enablePan={false}
enableZoom={true}
maxPolarAngle={Math.PI / 2}
minPolarAngle={Math.PI / 2}
/>
<Earth isMobile={isMobile} />
</Suspense>
<Preload all />
</Canvas>
);
};
export default EarthCanvas;