Fog
Fog hides the far plane and adds atmosphere. Linear for explicit near/far, exponential for natural haze.
Three.js — fog
EXAMPLE
import * as THREE from 'three';
const scene = new THREE.Scene();
scene.background = new THREE.Color(0xc6d8ff);
// ===== Linear fog: clear near 'near', fully fogged at 'far' =====
scene.fog = new THREE.Fog(0xc6d8ff, /*near*/ 10, /*far*/ 80);
// Anything closer than 10 units = clear; past 80 = pure fog colour.
// ===== Exponential fog: density-based, more natural =====
scene.fog = new THREE.FogExp2(0xc6d8ff, /*density*/ 0.02);
// Higher density = thicker fog; no near/far cutoffs.
// ===== Match fog colour to scene clear colour =====
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setClearColor(scene.background);
// If fog colour != clear colour, distant geometry pops against the background.
// Easy win: set both to the same colour and update them together.
// ===== Camera setup matters =====
const camera = new THREE.PerspectiveCamera(60, innerWidth/innerHeight, 0.1, 200);
camera.far = 200; // must be at least as far as fog's far for visible cutoff
camera.position.set(0, 5, 25);
// ===== Build a small world to see it =====
const ground = new THREE.Mesh(
new THREE.PlaneGeometry(400, 400),
new THREE.MeshStandardMaterial({ color: 0x88aa88 }),
);
ground.rotation.x = -Math.PI / 2;
scene.add(ground);
for (let i = 0; i < 80; i++) {
const box = new THREE.Mesh(
new THREE.BoxGeometry(1, 2, 1),
new THREE.MeshStandardMaterial({ color: 0x884444 }),
);
box.position.set((Math.random()-0.5)*100, 1, (Math.random()-0.5)*100);
scene.add(box);
}
scene.add(new THREE.DirectionalLight(0xffffff, 1).position.set(5, 10, 5));
scene.add(new THREE.AmbientLight(0xffffff, 0.4));
// ===== Per-material override =====
const matNoFog = new THREE.MeshBasicMaterial({ color: 0xffff00, fog: false });
// Useful for HUD-style billboards that shouldn't fade with distance.
// ===== Toggle at runtime =====
function setFog(kind, color, params) {
scene.background = new THREE.Color(color);
renderer.setClearColor(scene.background);
if (kind === 'linear') scene.fog = new THREE.Fog(color, params.near, params.far);
if (kind === 'exp') scene.fog = new THREE.FogExp2(color, params.density);
if (kind === 'none') scene.fog = null;
}
setFog('exp', 0xc6d8ff, { density: 0.025 });
// ===== Render loop =====
renderer.setSize(innerWidth, innerHeight);
document.body.append(renderer.domElement);
renderer.setAnimationLoop(() => renderer.render(scene, camera));
// ===== Patterns to internalise =====
// - Linear fog when you want a specific 'visible distance' (gameplay zones)
// - Exponential fog (FogExp2) for cinematic / outdoor scenes
// - Always sync fog colour with background and renderer clear colour
// - Set camera.far appropriately; fog cannot help with far-plane clipping
// - fog: false on UI/HUD materials so overlays stay readable
// ===== Pitfalls =====
// - Fog colour != background colour -> visible 'horizon line' where geometry ends
// - Density too high in FogExp2 -> scene blanks out near the camera
// - PointLights and fog interact through materials only; bake your lighting expectations
// - Custom ShaderMaterial needs fog uniforms explicitly; the built-in materials handle it
Why it matters
Fog is the cheapest atmosphere lever in three.js. Match its colour to the clear colour, pick linear for explicit zones or exponential for natural depth, and use fog: false on overlays. Two lines of code transform a flat scene into something that feels like a world.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Discussion
Loading…