Enable Shadows in React Three Fiber

The author
Stephen Castle4 years ago

When I was first learning React Three Fiber I remember having trouble getting shadows in my scene even though it's a pretty simple procedure. This post will be a quick reference to turning on simple shadows in your own scenes.

Step 1: Enable Shadows on the Canvas Element

In order to have any shadows in your scene you must first turn on shadows in the Canvas by adding the shadowMap prop to the component.

    <Canvas
      colorManagement
      shadowMap // highlight-line
      camera={{ position: [-3, 2, 5], fov: 90 }}
    >

Step 2: Enable Shadows on the Lights Which You want to Cast Shadows

To tell a light that it should cast shadows you need to set the castShadow prop on the light component to true as well. There are only 3 types of lights which can cast shadows normally. They are the DirectionalLight, the PointLight, and the SpotLight. No matter which type it is you still need to set this prop.

<directionalLight
  intensity={0.5}
  castShadow // highlight-line
  shadow-mapSize-height={512}
  shadow-mapSize-width={512}
/>

Another interesting thing to point out here are the shadow-mapSize-height and shadow-mapSize-width These are setting options on the lights shadow map, I'll do another tutorial about all of the options and how to get better looking shadows later. Just be aware there are in fact options you can set once you know how to access them.

Step 3: Enable the object which will cast a shadow to cast shadows.

Next you need to set a castShadow prop on every object in the scene you want to cast a shadow.

// highlight-next-line
<Box castShadow ref={boxRef} position={[0, 0.5, 0]}>
  <meshStandardMaterial attach="material" color="white" />
</Box>

Step 4: Enable objects which will have shadows cast on them to receive shadows.

The last step is to add a receiveShadow prop to any object that you want to have a shadow cast upon it by another object. Objects can have both the receiveShadow and the castShadow prop, but they don't always need both, like in this case where the ground is going to receive the cube's shadow, but not cast its own.

<Plane
  receiveShadow // highlight-line
  rotation={[-Math.PI / 2, 0, 0]}
  position={[0, -1, 0]}
  args={[1000, 1000]}
>
  <meshStandardMaterial attach="material" color="white" />
</Plane>

Finally if you have set all of these props you will start to see shadows, but not a moment sooner. Remember that the more lights and objects you have casting and receiving shadows, the slower your scene will perform, so be aware of which components you set these props on, don't just throw them on everything willy-nilly unless you want them.