šŸš€ LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
šŸŽ“ COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
HTML MASTER CLASS /// LEARN TAGS /// BUILD STRUCTURE /// SEMANTIC WEB /// HTML MASTER CLASS /// LEARN TAGS ///

The Scene in Three.js 3D WebGL

Learn about The Scene in this comprehensive Three.js 3D WebGL tutorial. Learn how to manipulate the Scene object, add backgrounds, and implement depth-based Fog.

⚔ Total XP: 0|šŸ’» threejs XP: 0

Skill Matrix

UNLOCK NODES BY LEARNING NEW TAGS.

System Hub

Core scene concepts.

Quick Quiz //

What happens if you create a mesh but never call scene.add() on it?


šŸš€ LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
šŸŽ“ COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.

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

1The Scene as a Container

The Scene is the container for everything. It's the 3D universe where you place your objects, lights, and cameras — nothing appears on screen unless it has been added to the scene graph first.

Internally, THREE.Scene is just a specialized THREE.Object3D that acts as the root of a tree. Every mesh, light, or group you add becomes a child node, and the renderer walks this tree each frame to figure out what to draw. This hierarchical structure is also what allows grouping: moving a parent object automatically moves every child along with it.

āœ•
—
+
const scene = new THREE.Scene();
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

2The Scene as a Movie Set

You can think of the Scene like a movie set. A movie set without actors, lights, or a camera isn't much to look at — the same is true of a THREE.Scene with nothing added to it.

The scene.add() method is how every actor joins that set: pass it any Object3D (a mesh, a light, a group, even another scene fragment) and it becomes part of the render tree from that point forward. Forgetting to call scene.add() on an object you've created is one of the most common reasons a Three.js object simply never appears.

āœ•
—
+
scene.add(cube);
scene.add(light);
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

3Customizing the Scene Background

You can also change the environment of the scene itself. Let's start by changing the background color of the universe — assigning a THREE.Color to scene.background instantly changes what fills the space outside your objects.

scene.background isn't limited to solid colors either; it also accepts a THREE.Texture or a THREE.CubeTexture, which is how skyboxes and environment reflections are typically implemented. The renderer paints this background before anything else each frame, so it always sits visually behind every object in the scene.

āœ•
—
+
scene.background = new THREE.Color('midnightblue');
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

4Scene Setup in React Three Fiber

In React Three Fiber, the Scene is created automatically by the Canvas component. To change the background color, we can just attach a color element to the scene's background property declaratively — no imperative scene.background = ... call needed.

This is a recurring R3F pattern: properties that Three.js sets imperatively on an object are instead expressed as JSX children with an attach prop telling R3F which property on the parent to assign the result to. It keeps scene configuration readable as part of your component tree instead of scattered across useEffect calls.

āœ•
—
+
const App = () => {
  return (
    <Canvas>
      <color attach="background" args={["#111122"]} />
      <mesh>
        <boxGeometry />
        <meshNormalMaterial />
      </mesh>
    </Canvas>
  );
};

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

5The attach Prop in R3F

In R3F, the attach prop on the color tag is what assigns it to the scene's background property specifically — attach="background" tells the reconciler 'set scene.background to the THREE.Color instance this tag creates.'

The args prop alongside it passes constructor arguments to the underlying Three.js class, exactly like it does for geometries — args={["#111122"]} is equivalent to calling new THREE.Color("#111122"). Together, attach and args let a single JSX tag replace what would otherwise be several lines of imperative setup code.

āœ•
—
+
<color ???='background' args={['red']} />
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

6Adding Fog for Depth

Another amazing feature of the Scene is Fog. Fog gradually fades objects into a specific color based on their distance from the camera, which is one of the cheapest ways to add a sense of scale and depth to a scene.

Beyond the aesthetic effect, fog is a practical performance tool: distant objects that fade completely into the fog color can often be culled from rendering entirely (a technique sometimes paired with far-plane clipping), since the viewer would never be able to see them clearly anyway.

āœ•
—
+
scene.fog = new THREE.Fog('#111122', 1, 10); // color, near, far
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

7Fog in React Three Fiber

Let's see Fog in action in React Three Fiber! Watch how the cubes fade into the dark background as they move further back — the fog tag with attach="fog" follows the exact same declarative pattern we used for the background color.

Notice that the fog's color in this example matches the scene's background color. This isn't a coincidence: fog blends objects toward its own color as distance increases, so mismatching fog and background colors produces a visible seam where fully-fogged objects meet the background instead of disappearing into it seamlessly.

āœ•
—
+
const SceneWithFog = () => {
  return (
    <Canvas camera={{ position: [0, 2, 5] }}>
      <color attach="background" args={["#111122"]} />
      <fog attach="fog" args={["#111122", 2, 8]} />
      
      <ambientLight intensity={0.5} />
      <directionalLight position={[10, 10, 10]} />
      
      {/* Front Cube - Clear */}
      <mesh position={[0, 0, 0]}>
        <boxGeometry />
        <meshStandardMaterial color="hotpink" />
      </mesh>
      
      {/* Middle Cube - Semi-fogged */}
      <mesh position={[2, 0, -3]}>
        <boxGeometry />
        <meshStandardMaterial color="hotpink" />
      </mesh>
      
      {/* Back Cube - Almost completely fogged */}
      <mesh position={[-2, 0, -6]}>
        <boxGeometry />
        <meshStandardMaterial color="hotpink" />
      </mesh>
    </Canvas>
  );
};

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

8Understanding Fog's Distance Arguments

THREE.Fog takes three arguments: a color, a near distance, and a far distance. Objects closer than near render with zero fog applied, objects at or beyond far are rendered fully in the fog color, and anything in between is linearly blended based on its distance from the camera.

Tuning near and far is mostly a matter of testing against your scene's actual scale — a near value that's too small makes even close objects look hazy, while a far value that's too large means distant objects never fully fade, undermining the depth cue fog is meant to provide.

āœ•
—
+
scene.fog = new THREE.Fog('#000', 1, ???);
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

9Wrapping Up Scene Fundamentals

Excellent! You now know how to set the stage for your 3D world using the Scene, Backgrounds, and Fog — the environmental building blocks that every Three.js project relies on before a single interactive object is added.

In the next lesson, we'll turn to the Camera: the object that determines exactly what portion of this scene is actually visible, and how perspective and framing affect the final image the renderer produces.

āœ•
—
+
// 🌌 Universe created successfully!
localhost:3000
Browser Preview
WebGL Output
3D Scene rendered. Objects: 4, Draw Calls: Optimized.

10Step-by-Step Breakdown

The Scene is the container for everything. It's the 3D universe where you place your objects, lights, and cameras.

You can think of the Scene like a movie set. A movie set without actors, lights, or a camera isn't much to look at.

Which method is used to put an object into the scene?

  • →push
  • →add
  • →insert

You can also change the environment of the scene itself. Let's start by changing the background color of the universe.

In React Three Fiber, the Scene is created automatically by the <Canvas>. To change the background color, we can just attach a color to the scene's background property.

In R3F, which prop is used on the <color> tag to assign it to the scene's background?

  • →assign
  • →set
  • →attach

Another amazing feature of the Scene is Fog. Fog gradually fades objects into a specific color based on their distance from the camera.

Let's see Fog in action in React Three Fiber! Watch how the cubes fade into the dark background as they move further back.

What does the third argument in new THREE.Fog(color, near, far) represent?

  • →Density of the fog
  • →Maximum distance before full fog
  • →Minimum distance

Excellent! You now know how to set the stage for your 3D world using the Scene, Backgrounds, and Fog.

Level Up šŸš€

Advanced cheat sheets, SEO tricks, and interview prep for this topic.

Browser Support

ChromeSupported

Fully supported.

FirefoxSupported

Fully supported.

SafariSupported

Fully supported.

EdgeSupported

Fully supported.

Accessibility (A11y)

1Announce Scene-Level Changes That Aren't Visually Obvious

A fog or background color change communicates mood or depth visually, but conveys nothing to a screen reader user — if such a change is tied to an important state transition (like 'entering a new level'), announce that transition via an aria-live region rather than relying on the visual cue alone.

<div aria-live="polite">Now entering the misty forest zone.</div>

SEO Implications

  • 1

    Scene Configuration Is Runtime State, Not Crawlable Content

    scene.background and scene.fog only exist once WebGL has initialized in the browser — none of it is present in server-rendered HTML or visible to a crawler, so this page's search value comes entirely from the surrounding written explanation of how the Scene API works, not from any specific fog color or background value.

Best Practices

Match Fog Color to Background Color for a Seamless Blend

If your fog's color doesn't match the scene's background, fully-fogged objects will visibly blend into a different color than the empty background behind them, creating an obvious seam. Keep both colors identical unless you deliberately want that contrast.

Tune Fog's near/far Values to Your Scene's Actual Scale

Default or copy-pasted fog distances rarely match a new scene's dimensions. Test near and far against your camera's typical viewing distance so nearby objects aren't hazy and distant objects actually fade out before the camera's far clipping plane.

Frequent Bugs

THE BUG

Setting scene.background or scene.fog on the underlying Three.js scene object directly inside a React Three Fiber component's render body, causing it to be reassigned on every re-render.

THE FIX

In R3F, express scene-level properties declaratively with the <color attach="background"> and <fog attach="fog"> tags instead of imperatively mutating the scene object — this lets React's reconciliation handle updates efficiently instead of reassigning the property on every render pass.

Real-World Examples

Depth Cueing in a Racing Game's Track Environment

Racing and flight-sim style Three.js experiences commonly combine a matching scene.background color with THREE.Fog to make distant terrain fade smoothly into the horizon, both hiding the harsh edge of the camera's draw distance and reducing the number of distant objects the GPU needs to fully render each frame.

scene.background = new THREE.Color('#87CEEB');
scene.fog = new THREE.Fog('#87CEEB', 50, 500);

Interview Prep

?Frequently Asked Questions

Pascual Vila

Pascual Vila

Frontend Instructor // Code Syllabus

Common Pitfalls & Errors

The Error //

Not reading error messages carefully

Uncaught TypeError: Cannot read properties of undefined (reading 'length') // Solution: Ensure the variable you are calling .length on is initialized as a string or an array, not undefined.

The Solution //

Most of the time, the compiler or interpreter tells you exactly what line caused the crash and why. Read stack traces from the top down to identify the root cause.

The Error //

Hardcoding sensitive credentials

// Wrong const API_KEY = 'sk-123456789'; // Correct const API_KEY = process.env.API_KEY;

The Solution //

Never hardcode API keys, passwords, or secrets in your source code. Use environment variables (.env files) to keep them secure and out of version control.

Continue Learning