Search code examples
reactjsthree.jsreact-three-fiberreact-three-dreithree-tier

React drei fix light direction with orbit control


I have a simple code, and I want to ensure that the light direction always comes from the positive z-axis. Even if I rotate the object, the well-lit side should be facing the front, and the light source should remain stationary.

Here is the codesandbox link. https://codesandbox.io/p/sandbox/three-light-cjmpwf

Here is my code.

import { Canvas } from "@react-three/fiber";
import { OrbitControls } from "@react-three/drei";

import "./styles.css";

export default function App() {
  return (
    <div className="main">
      <Canvas>
        <directionalLight position={[0, 0, 2]} intensity={10} />
        <OrbitControls enableZoom={false} enablePan={false} />
        <mesh>
          <capsuleGeometry args={[1, 1, 32]} />
          <meshStandardMaterial color={"red"} />
        </mesh>
      </Canvas>
    </div>
  );
}

Currently, when I rotate the capsule, the directional light source also rotates with it. I would like to keep the light direction fixed, always coming from the top, regardless of the object's rotation.

Here's an example image illustrating the issue. How can I modify the code to achieve a fixed light direction while rotating the object?

enter image description here


Solution

  • "...Currently, when I rotate the capsule, the directional light source also rotates with it..."

    You don't move the capsule or the light, OrbitControls "moves" the camera, or I should say updating position of it. And since the light is stationary, that's why you experience this problem.

    import React, { useRef } from "react";
    import { Canvas, useFrame, useThree } from "@react-three/fiber";
    import { OrbitControls } from "@react-three/drei";
    import "./styles.css";
    
    function FollowCameraLight() {
      const lightRef = useRef();
      const { camera } = useThree();
    
      useFrame(() => {
        lightRef.current.position.copy(camera.position);
      });
    
      return (
        <directionalLight ref={lightRef} intensity={10} />
      );
    }
    
    export default function App() {
      return (
        <div className="main">
          <Canvas>
            <FollowCameraLight />
            <OrbitControls enableZoom={false} enablePan={false} />
            <mesh>
              <capsuleGeometry args={[1, 1, 32]} />
              <meshStandardMaterial color={"red"} />
            </mesh>
          </Canvas>
        </div>
      );
    }
    

    https://codesandbox.io/p/sandbox/three-light-forked-5ths4p?file=%2Fsrc%2FApp.js%3A33%2C1