Navigate

Search topics across all sections

GitHub
Transforms & Color

Fog & Atmosphere

Fog adds depth, mood, and atmosphere to your scene. Nearby objects stay clear while distant ones gradually fade into the mist. Three.js provides two fog types: linear (Fog) fades between two distances, and exponential (FogExp2) creates a more natural, density-based haze.

You add fog to your scene to create atmosphere. The objects fade nicely into the distance — but they fade to white, while your background is pitch black. There's a jarring line where the foggy objects meet the background. It looks like a rendering bug, but it's just mismatched colors.

terminal
Visible seam between foggy objects and background. Objects fade to white, background is black.

Real-world

Think of fog as morning mist on a country road.

When you drive through fog, the car ahead of you is clear. The one two cars ahead is hazy. The buildings at the end of the street are ghostly silhouettes. And beyond that? Just... mist.

Linear fog (Fog) is like a wall of mist — everything before a certain distance is clear, everything after it is invisible, and there's a smooth gradient in between. You control where the fog starts and stops.

Exponential fog (FogExp2) is like real atmospheric haze — it gets thicker the deeper you go, with no hard cutoff. A single density value controls how quickly things disappear. It feels more natural but is harder to fine-tune.

Near Objects

Fully visible, no fog

Mid Distance

Partially blended with fog

Far Objects

Almost invisible, mostly fog

Background

100% fog color

Hands-On: Adding Atmosphere

Let's add fog to a scene and see how it transforms the mood. We'll start with linear fog, then switch to exponential, and learn why the background color matters.

Step 1: Linear Fog (Fog)

App.tsxTSX
// In R3F, attach fog to the scene
<Canvas>
  {/* Linear fog: color, near, far */}
  <fog attach="fog" args={["#1a1a2e", 5, 20]} />

  {/* IMPORTANT: match background to fog color */}
  <color attach="background" args={["#1a1a2e"]} />

  <ambientLight intensity={0.3} />
  <MyScene />
</Canvas>

// Objects closer than 5 = fully visible
// Objects between 5-20 = gradually fading
// Objects beyond 20 = completely hidden

Linear fog takes three arguments: color, near distance, and far distance. Everything between near and far gets progressively blended with the fog color. Always match the scene background to the fog color for a seamless transition.

Step 2: Exponential Fog (FogExp2)

App.tsxTSX
// Exponential fog: color, density
<Canvas>
  <fogExp2 attach="fog" args={["#1a1a2e", 0.08]} />
  <color attach="background" args={["#1a1a2e"]} />
  <MyScene />
</Canvas>

// Density controls how quickly fog thickens
// 0.01 = very light haze
// 0.05 = moderate fog
// 0.15 = dense pea-soup fog
// 0.30 = can barely see your hand

Exponential fog uses a density value instead of near/far distances. The fog thickens according to an exponential curve, which more closely mimics how real atmospheric scattering works. Lower density = clearer, higher density = thicker.

Step 3: Dynamic fog for mood changes

App.tsxTSX
function DynamicFog() {
  const { scene } = useThree();

  const { fogColor, density } = useControls({
    fogColor: "#1a1a2e",
    density: { value: 0.08, min: 0, max: 0.3 }
  });

  useEffect(() => {
    scene.fog = new THREE.FogExp2(fogColor, density);
    scene.background = new THREE.Color(fogColor);
    return () => { scene.fog = null; };
  }, [scene, fogColor, density]);

  return null;
}

You can update fog properties dynamically — transition from clear skies to dense fog for a horror game, or shift fog color as time of day changes. Animate fog density in useFrame for gradual transitions.

What you just learned

Linear fog (Fog) fades objects between a near and far distance — simple to control with exact boundaries.

Exponential fog (FogExp2) uses a density value for more natural atmospheric haze with no hard cutoff.

Always match the scene background color to the fog color to avoid visible seams at the fog boundary.

Fog can be updated dynamically at runtime for atmospheric transitions and mood changes.

Question

Beyond visual atmosphere, fog has a practical benefit: it hides the "edge of the world" where your scene runs out of content. How might game developers use fog strategically to manage what players can and can't see?

Think about it...

You have linear fog with near=5 and far=15. An object is at distance 10 from the camera. How much fog is applied?

Hint: Linear fog interpolates from 0% at the near distance to 100% at the far distance...

Try These Challenges

Put what you learned into practice. Try each challenge in the demo above using the Leva controls, then check the solution.

Try This!

Beginner

Set fog to exponential — thicker!

Try This!

Beginner

Change fog color to red — Mars!

Try This!

Beginner

Set density to 0 — crystal clear

These are the patterns that trip up developers most often. Switch between Wrong and Fixed to compare the code side by side.

1
Fog color doesn't match the background
Objects fade into gray while the background is black — visible seam at the fog boundary
Don't do this
App.tsxTSX
// Fog fades to white, background is black!
<Canvas>
  <fog attach="fog" args={["#ffffff", 1, 15]} />
  {/* Background is default black */}
  <MyScene />
</Canvas>
Fog blends objects toward the fog color as they recede. If that color doesn't match your background, distant objects will fade to one color but the background is another, creating an ugly visible boundary. Always match them.
2
Using Fog with transparent or unlit materials
MeshBasicMaterial ignores fog by default, creating floating objects
Don't do this
App.tsxTSX
// Some materials don't respond to fog!
<fog attach="fog" args={["#333", 1, 10]} />

// This object ignores fog entirely:
<mesh position={[0, 0, -20]}>
  <boxGeometry />
  <meshBasicMaterial color="red" fog={false} />
</mesh>
By default, MeshBasicMaterial has fog enabled, but if you explicitly set fog={false} or use custom shaders, objects will ignore fog and appear to float. Always check that fog={true} on all materials in a foggy scene.
3
Fog near plane set too close to the camera
Everything looks foggy, even objects right in front of you
Don't do this
App.tsxTSX
// Near = 0 means fog starts at the camera!
<fog attach="fog" args={["#333", 0, 10]} />
// Even objects at position [0,0,0] are foggy
Linear fog blends from 0% at the near distance to 100% at the far distance. If near is 0, fog starts immediately at the camera. Push it out so that nearby objects remain clear and only distant objects fade.

Best Practices

Match Fog and Background

Always set the scene background color to match the fog color. This creates a seamless transition as objects fade into the distance.

Use Fog for Performance

Set the camera's far plane to match the fog's far distance. Objects beyond the fog are invisible anyway — skip rendering them entirely by clipping them out.

FogExp2 for Outdoor Scenes

Exponential fog mimics real atmospheric scattering better than linear. Use it for outdoor environments, forests, and large open worlds where you want natural-looking haze.

Animate Fog for Transitions

Gradually change fog density and color over time for day/night cycles, weather effects, or entering a mysterious cave. Smooth fog transitions feel much better than instant switches.