Bonjour ! Dans la leçon précédente, nous avons appris à sculpter l'atmosphère de nos scènes en configurant les propriétés fondamentales des lumières : leur couleur, leur intensité et leur portée. Vous savez maintenant donner un caractère unique à chaque source lumineuse.
Aujourd'hui, nous allons ajouter une dimension de réalisme indispensable : les ombres. Sans ombres, les objets flottent dans l'espace ; avec elles, ils s'ancrent dans la scène, révèlent leur volume et interagissent de manière crédible avec leur environnement. L'objectif de cette leçon est de vous apprendre à mettre en place des ombres portées en configurant le renderer, les lumières et les objets.
Ce processus se décompose en trois étapes logiques que nous allons suivre pas à pas.
La Mécanique des Ombres dans Three.js
Ajouter des ombres n'est pas une simple case à cocher. C'est un processus en trois parties qui implique :
- Le Moteur de Rendu (
renderer) : Il faut d'abord lui dire d'activer le calcul des ombres, une fonctionnalité coûteuse en performance et donc désactivée par défaut. - Les Lumières (
light) : Seules certaines lumières peuvent projeter des ombres. Il faut explicitement désigner lesquelles le feront. - Les Objets (
mesh) : Enfin, il faut spécifier quels objets projettent des ombres et quels objets peuvent en recevoir sur leur surface.
Pour nous guider, nous allons nous appuyer sur un excellent article qui détaille précisément ces étapes.
Ajouter des Ombres Dynamiques à ta Scène 3D en Three.js - Syslog
Cet article, "Ajouter des Ombres Dynamiques à ta Scène 3D en Three.js", sera notre fil conducteur. Il est clair, en français, et contient tous les extraits de code dont nous aurons besoin. Nous allons le parcourir étape par étape.
Pour l'instant, lisez les sections intitulées "Étape 1" à "Étape 4". Ne vous préoccupez pas d'intégrer le code tout de suite, concentrez-vous sur la compréhension de la logique derrière chaque étape.
Maintenant que vous avez une vue d'ensemble, décortiquons chaque étape en détail.
Étape 1 : Activer les Ombres sur le Moteur de Rendu
Comme vous l'avez lu dans l'article, la première chose à faire est d'autoriser le renderer à calculer ce qu'on appelle des "shadow maps" (cartes d'ombres).
// Activer le calcul des ombres
renderer.shadowMap.enabled = true;
// Optionnel : choisir un algorithme pour des ombres plus douces
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
shadowMap.enabled = true;est l'interrupteur principal. Sans cette ligne, rien ne se passera.shadowMap.type = THREE.PCFSoftShadowMap;adoucit les bords des ombres, ce qui évite un effet "escalier" ou pixelisé et donne un résultat beaucoup plus naturel. Il existe d'autres types, mais celui-ci offre un excellent compromis entre qualité et performance.
L'image suivante illustre bien la différence entre des ombres "dures" (à gauche) et des ombres douces et filtrées (à droite). Le PCFSoftShadowMap nous aide à nous rapprocher du résultat de droite.

Étape 2 : Configurer une Lumière pour Projeter des Ombres
Toutes les lumières ne sont pas capables de projeter des ombres. Les lumières qui illuminent toute la scène uniformément, comme AmbientLight, ne le peuvent pas. En revanche, les lumières qui ont une direction ou une position précise, comme DirectionalLight, PointLight et SpotLight, le peuvent.
Concentrons-nous sur la DirectionalLight, qui simule le soleil. Pour qu'elle projette une ombre, il faut faire deux choses :
- L'activer avec
castShadow. - Configurer sa "caméra d'ombre".
const directionalLight = new THREE.DirectionalLight(0xffffff, 1.0);
directionalLight.position.set(5, 10, 5);
// 1. Activer la projection d'ombre pour CETTE lumière
directionalLight.castShadow = true;
// 2. Configurer la "caméra d'ombre"
directionalLight.shadow.mapSize.width = 1024;
directionalLight.shadow.mapSize.height = 1024;
directionalLight.shadow.camera.near = 0.5;
directionalLight.shadow.camera.far = 50;
Qu'est-ce que la "caméra d'ombre" ?
Pour calculer une ombre, Three.js place une caméra virtuelle à la position de la lumière et "regarde" la scène de ce point de vue. Tout ce qui est caché de la lumière est considéré comme étant dans l'ombre.

shadow.mapSizedéfinit la résolution de cette "photo" prise par la lumière. Plus la résolution est élevée (ex: 2048x2048), plus l'ombre sera nette, mais plus le calcul sera gourmand en ressources.1024x1024est un bon point de départ.shadow.cameradéfinit le volume (le frustum) de cette caméra. Avecnearetfar, vous délimitez la zone de calcul. Il est crucial d'ajuster ce volume pour qu'il soit le plus serré possible autour de votre scène. Un volume trop grand diluera la résolution de votremapSizeet produira des ombres de mauvaise qualité.
Étape 3 : Configurer les Objets
La dernière étape consiste à dire à chaque objet comment il doit se comporter vis-à-vis des ombres. Un objet peut :
- Projeter une ombre :
castShadow - Recevoir une ombre sur sa surface :
receiveShadow
// Un cube qui projette une ombre, mais n'en reçoit pas forcément
const cube = new THREE.Mesh(geometry, material);
cube.castShadow = true;
// cube.receiveShadow = false; // Par défaut
// Un sol qui reçoit les ombres, mais n'en projette pas (il est plat)
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.receiveShadow = true;
// plane.castShadow = false; // Par défaut
Un objet peut bien sûr faire les deux ! Un personnage posé sur le sol pourrait avoir castShadow = true pour projeter son ombre sur le sol, et receiveShadow = true pour qu'une ombre d'un autre objet (un arbre, par exemple) puisse se projeter sur lui.
Atelier Pratique : Créons des Ombres
Il est temps de mettre tout cela en application. Reprenez le code de votre scène, ou partez de ce modèle de base, et suivez les étapes pour ajouter des ombres.
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
// 1. Scène, Caméra, Renderer de base
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(4, 5, 7);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const controls = new OrbitControls(camera, renderer.domElement);
// --- VOTRE MISSION COMMENCE ICI ---
// TODO Étape 1: Configurez le renderer pour les ombres
// renderer.shadowMap.enabled = ...
// renderer.shadowMap.type = ...
// 2. Lumières
const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(10, 15, 5);
scene.add(directionalLight);
// TODO Étape 2: Configurez la lumière directionnelle
// directionalLight.castShadow = ...
// Configurez la mapSize (width/height) et la camera (near/far) de son ombre.
// 3. Objets
const sphereGeometry = new THREE.SphereGeometry(1, 32, 32);
const sphereMaterial = new THREE.MeshStandardMaterial({ color: 0x0077ff });
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.y = 1;
scene.add(sphere);
// TODO Étape 3 (partie A): Le sphere doit projeter une ombre.
// sphere.castShadow = ...
const planeGeometry = new THREE.PlaneGeometry(20, 20);
const planeMaterial = new THREE.MeshStandardMaterial({ color: 0xcccccc });
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = -Math.PI / 2;
scene.add(plane);
// TODO Étape 3 (partie B): Le sol doit recevoir cette ombre.
// plane.receiveShadow = ...
// --- FIN DE LA MISSION ---
// Boucle d'animation
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
animate();
Prenez 15 minutes pour compléter les sections TODO. N'hésitez pas à vous référer à nouveau à l'article LINK ou aux extraits de code ci-dessus. Observez bien le résultat après chaque modification. Essayez de changer les valeurs de mapSize ou de far pour voir leur impact.
Note sur les autres types de lumières
La PointLight peut aussi projeter des ombres. La syntaxe est la même : pointLight.castShadow = true;. L'article "Tutoriel Three.js" de Florian Gouloubi (ressource LINK) en montre un exemple. Cependant, la configuration de son ombre est un peu plus complexe et coûteuse, car elle doit projeter dans toutes les directions. Pour l'instant, maîtriser les ombres directionnelles est l'essentiel.
Conclusion
Excellent travail ! Vous avez ajouté une couche de réalisme fondamental à vos scènes. Les ombres ne sont plus un mystère.
Points clés à retenir :
- L'ajout d'ombres est un processus en trois étapes : configurer le renderer, la lumière et les objets.
renderer.shadowMap.enabled = true;est le point de départ obligatoire.- Seules certaines lumières (
DirectionalLight,PointLight,SpotLight) peuvent projeter des ombres aveclight.castShadow = true;. - Les objets doivent être explicitement marqués pour projeter (
castShadow) ou recevoir (receiveShadow) des ombres. - La qualité des ombres est un compromis entre performance et réalisme, principalement contrôlé par
shadow.mapSizeet le réglage précis de lashadow.camera.
Aperçu de la prochaine leçon :
Maintenant que vous maîtrisez les lumières et les ombres, nous allons apprendre à les orchestrer de manière professionnelle. La prochaine leçon sera consacrée à une technique d'éclairage classique utilisée au cinéma et en photographie : l'éclairage à trois points (key, fill, back). Vous apprendrez à utiliser plusieurs lumières en harmonie pour sculpter et valoriser vos modèles 3D.