skip to Main Content

I need to illuminate a sphere with two directional lights, one in front to illuminate the front of the sphere like sunlight. And one towards the back to display the light of the cities. To do this, I play with layers to explain how light affects the material.

My issue is that the two lights do not seem to illuminate to the respective ends of the sphere. I tried increasing the intensity, the scale, the distance…

I recreated a simplified version of my code to illustrate:

export default function Earth(): JSX.Element {
  const earthMapRef = useRef<any>();
  const frontLightRef = useRef<any>();
  const backLightRef = useRef<any>();

  useHelper(frontLightRef, DirectionalLightHelper, 1, 'red');
  useHelper(backLightRef, DirectionalLightHelper, 1, 'red');

  return (
    <Fragment>
      <PivotControls anchor={[0, 0, 0]} depthTest={false} scale={0.5} visible={true}>
        <mesh ref={earthMapRef} position={[0, 0, 0]}>
          <sphereGeometry args={[1, 64, 64]} />
          <meshStandardMaterial />
        </mesh>
      </PivotControls>

      <directionalLight
        ref={frontLightRef}
        position={[0, 0, 5]}
        scale={[3, 3, 3]}
        intensity={Math.PI}
        color="#FFFFFF"
      />

      <directionalLight
        ref={backLightRef}
        position={[0, 0, -5]}
        scale={[3, 3, 3]}
        intensity={Math.PI}
        color="#FFFFFF"
      />
    </Fragment>
  );
}

screenshot of result

Thanks!

2

Answers


  1. This reminds me a bit of a case from this thread:
    React drei fix light direction with orbit control

    My solution there was based on general illumination. Maybe it will be good if you move in this direction, by mixing lights or/and global illumination?

    I modified it a bit by giving it three lights. The main one illuminating the "black space" and two directional ones on both sides. Perhaps you will find the right parameters.

    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>
            <directionalLight position={[0, 0, 2]} intensity={5} />
            <directionalLight position={[0, 0, -2]} intensity={5} />
            <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%3A8%2C33

    Login or Signup to reply.
  2. This result makes totally sense IMO. In other words you cannot illuminate the entire half of a sphere with those lights in that scene.

    You have a sphere and one light in front and one at the back (exact opposite of eachother). That still means the sides of the sphere will not receive any light, since the light rays won’t intersect those parts of the sphere.
    The angle between the light rays and the sphere surface in that black area is 90 degrees (for the whole circumferance of the sphere).

    Maybe you should consider adding an ambient light? See: https://threejs.org/docs/#api/en/lights/AmbientLight

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search