HTML MASTER CLASS /// LEARN TAGS /// BUILD STRUCTURE /// SEMANTIC WEB /// HTML MASTER CLASS /// LEARN TAGS ///
Total XP: 0|💻 threejs XP: 0

Shadows in Three.js 3D WebGL

Understand the 4-step process to enable shadows in Three.js and how to optimize shadow map resolution.

LOADING ENGINE...

Skill Matrix

UNLOCK NODES BY LEARNING NEW TAGS.

System Hub

Core AI logic.

Quick Quiz //

What is the primary danger of ignoring this AI concept?


Listen up. If you're building modern applications, understanding Shadows in Three.js 3D WebGL is non-negotiable. This is where simple logic turns into intelligent behavior.

1Threejs shadows Part 1

Lights are great, but without shadows, objects look like they are floating in space. Shadows ground your objects and add immense realism.

Look, here's the reality in production: if you don't fully grasp this, you're going to introduce massive bottlenecks or incorrect predictions. I've seen junior devs deploy models that hallucinate wildly because they missed this exact nuance. It's all about understanding the data pipeline and model parameters.

Let's break down the code. Notice how we're structuring this logic. We aren't just hacking things together; we're designing for scale and accuracy. If you mess up the inference loop or create new tensors every frame here, the runtime won't optimize it, and you'll get massive memory leaks. Always follow ML engineering best practices.

+
// 🦇 Enter the shadows
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

2Threejs shadows Part 2

Shadows in Three.js are expensive to compute. Therefore, they are turned OFF by default everywhere. You must explicitly enable them in 4 different places.

Look, here's the reality in production: if you don't fully grasp this, you're going to introduce massive bottlenecks or incorrect predictions. I've seen junior devs deploy models that hallucinate wildly because they missed this exact nuance. It's all about understanding the data pipeline and model parameters.

Let's break down the code. Notice how we're structuring this logic. We aren't just hacking things together; we're designing for scale and accuracy. If you mess up the inference loop or create new tensors every frame here, the runtime won't optimize it, and you'll get massive memory leaks. Always follow ML engineering best practices.

+
// 1. Renderer
// 2. Light
// 3. Object casting shadow
// 4. Object receiving shadow
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

3Threejs shadows Part 3

Step 1: You must tell the Renderer that it is allowed to calculate shadows.

Look, here's the reality in production: if you don't fully grasp this, you're going to introduce massive bottlenecks or incorrect predictions. I've seen junior devs deploy models that hallucinate wildly because they missed this exact nuance. It's all about understanding the data pipeline and model parameters.

Let's break down the code. Notice how we're structuring this logic. We aren't just hacking things together; we're designing for scale and accuracy. If you mess up the inference loop or create new tensors every frame here, the runtime won't optimize it, and you'll get massive memory leaks. Always follow ML engineering best practices.

+
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

4Threejs shadows Part 4

In React Three Fiber, you simply add the shadows prop to the <Canvas> component to enable shadows on the renderer.

Look, here's the reality in production: if you don't fully grasp this, you're going to introduce massive bottlenecks or incorrect predictions. I've seen junior devs deploy models that hallucinate wildly because they missed this exact nuance. It's all about understanding the data pipeline and model parameters.

Let's break down the code. Notice how we're structuring this logic. We aren't just hacking things together; we're designing for scale and accuracy. If you mess up the inference loop or create new tensors every frame here, the runtime won't optimize it, and you'll get massive memory leaks. Always follow ML engineering best practices.

+
<Canvas shadows>
  {/* Scene */}
</Canvas>
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

5Threejs shadows Part 5

What prop do you add to the <Canvas> in React Three Fiber to enable the shadow map on the renderer?

Look, here's the reality in production: if you don't fully grasp this, you're going to introduce massive bottlenecks or incorrect predictions. I've seen junior devs deploy models that hallucinate wildly because they missed this exact nuance. It's all about understanding the data pipeline and model parameters.

Let's break down the code. Notice how we're structuring this logic. We aren't just hacking things together; we're designing for scale and accuracy. If you mess up the inference loop or create new tensors every frame here, the runtime won't optimize it, and you'll get massive memory leaks. Always follow ML engineering best practices.

+
<Canvas ???>
  <mesh />
</Canvas>
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

6Threejs shadows Part 6

Step 2: Tell a specific Light that it should generate shadows. Not all lights can cast shadows (e.g., AmbientLight cannot).

Look, here's the reality in production: if you don't fully grasp this, you're going to introduce massive bottlenecks or incorrect predictions. I've seen junior devs deploy models that hallucinate wildly because they missed this exact nuance. It's all about understanding the data pipeline and model parameters.

Let's break down the code. Notice how we're structuring this logic. We aren't just hacking things together; we're designing for scale and accuracy. If you mess up the inference loop or create new tensors every frame here, the runtime won't optimize it, and you'll get massive memory leaks. Always follow ML engineering best practices.

+
directionalLight.castShadow = true;
// R3F:
<directionalLight castShadow />
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

7Threejs shadows Part 7

Step 3 & 4: Tell the objects what to do. The object blocking the light must castShadow. The object behind it must receiveShadow.

Look, here's the reality in production: if you don't fully grasp this, you're going to introduce massive bottlenecks or incorrect predictions. I've seen junior devs deploy models that hallucinate wildly because they missed this exact nuance. It's all about understanding the data pipeline and model parameters.

Let's break down the code. Notice how we're structuring this logic. We aren't just hacking things together; we're designing for scale and accuracy. If you mess up the inference loop or create new tensors every frame here, the runtime won't optimize it, and you'll get massive memory leaks. Always follow ML engineering best practices.

+
<mesh castShadow>
  <boxGeometry />
</mesh>

<mesh receiveShadow position={[0, -1, 0]}>
  <planeGeometry />
</mesh>
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

8Threejs shadows Part 8

If you have a cube sitting on a floor, what should the floor

Look, here's the reality in production: if you don't fully grasp this, you're going to introduce massive bottlenecks or incorrect predictions. I've seen junior devs deploy models that hallucinate wildly because they missed this exact nuance. It's all about understanding the data pipeline and model parameters.

Let's break down the code. Notice how we're structuring this logic. We aren't just hacking things together; we're designing for scale and accuracy. If you mess up the inference loop or create new tensors every frame here, the runtime won't optimize it, and you'll get massive memory leaks. Always follow ML engineering best practices.

+
<mesh ???>
  <planeGeometry /> {/* The Floor */}
</mesh>
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

9Threejs shadows Part 9

Let

Look, here's the reality in production: if you don't fully grasp this, you're going to introduce massive bottlenecks or incorrect predictions. I've seen junior devs deploy models that hallucinate wildly because they missed this exact nuance. It's all about understanding the data pipeline and model parameters.

Let's break down the code. Notice how we're structuring this logic. We aren't just hacking things together; we're designing for scale and accuracy. If you mess up the inference loop or create new tensors every frame here, the runtime won't optimize it, and you'll get massive memory leaks. Always follow ML engineering best practices.

+
const App = () => {
  return (
    <Canvas shadows camera={{ position: [0, 2, 5] }}>
      <ambientLight intensity={0.5} />
      {/* Light casting shadow */}
      <directionalLight 
        castShadow 
        position={[2.5, 5, 2.5]} 
        intensity={2} 
        shadow-mapSize={[1024, 1024]}
      />
      
      {/* Object casting shadow */}
      <mesh castShadow position={[0, 1, 0]}>
        <sphereGeometry args={[0.8, 32, 32]} />
        <meshStandardMaterial color="hotpink" />
      </mesh>
      
      {/* Floor receiving shadow */}
      <mesh receiveShadow rotation={[-Math.PI / 2, 0, 0]}>
        <planeGeometry args={[10, 10]} />
        <meshStandardMaterial color="white" />
      </mesh>
    </Canvas>
  );
};

render(<App />);
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

10Threejs shadows Part 10

Shadows look pixelated by default. To fix this, you must increase the light

Look, here's the reality in production: if you don't fully grasp this, you're going to introduce massive bottlenecks or incorrect predictions. I've seen junior devs deploy models that hallucinate wildly because they missed this exact nuance. It's all about understanding the data pipeline and model parameters.

Let's break down the code. Notice how we're structuring this logic. We aren't just hacking things together; we're designing for scale and accuracy. If you mess up the inference loop or create new tensors every frame here, the runtime won't optimize it, and you'll get massive memory leaks. Always follow ML engineering best practices.

+
// R3F
<directionalLight shadow-mapSize={[1024, 1024]} />

// Vanilla
light.shadow.mapSize.width = 1024;
light.shadow.mapSize.height = 1024;
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

11Threejs shadows Part 11

Awesome! Your scenes now have depth and grounding. Remember, shadows are performance-heavy, so use them sparingly.

Look, here's the reality in production: if you don't fully grasp this, you're going to introduce massive bottlenecks or incorrect predictions. I've seen junior devs deploy models that hallucinate wildly because they missed this exact nuance. It's all about understanding the data pipeline and model parameters.

Let's break down the code. Notice how we're structuring this logic. We aren't just hacking things together; we're designing for scale and accuracy. If you mess up the inference loop or create new tensors every frame here, the runtime won't optimize it, and you'll get massive memory leaks. Always follow ML engineering best practices.

+
// 🌘 Shadows rendered!
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

?Frequently Asked Questions

Pascual Vila

Pascual Vila

Frontend Instructor // Code Syllabus

Continue Learning