Bonjour !
Dans la leçon précédente, nous avons fait un grand pas en avant en apprenant à appliquer une texture de couleur (map) à nos objets. Au lieu d'une simple couleur unie, nos objets peuvent maintenant avoir des motifs complexes. Cependant, vous avez peut-être remarqué que même avec une texture, la surface semble encore un peu "plate" et manque de détails subtils qui la rendraient vraiment crédible.
Aujourd'hui, nous allons débloquer un niveau de réalisme supérieur. L'objectif de cette leçon est d'apprendre à utiliser les textures PBR essentielles (normalMap, roughnessMap, et aoMap) pour ajouter du réalisme. C'est le secret derrière les matériaux photoréalistes que vous voyez dans les jeux vidéo et les applications web 3D modernes.
Au-delà de la couleur : le Rendu Physique Réaliste (PBR)
Le PBR (Physically Based Rendering) est une approche qui vise à simuler la manière dont la lumière interagit avec les matériaux dans le monde réel. Au lieu d'utiliser une seule texture pour la couleur, on en utilise plusieurs, chacune décrivant une propriété physique spécifique de la surface.

Nous allons nous concentrer sur trois de ces cartes essentielles :
normalMap: Simule les détails de surface (relief, bosses, creux) sans ajouter de polygones.roughnessMap: Contrôle la rugosité de la surface, déterminant si elle est brillante ou mate.aoMap: Ajoute des ombres de contact subtiles, renforçant la perception de la profondeur.
Pour une définition formelle de ces cartes en français, la ressource suivante est parfaite.
Les matériaux — JavaScript avancé
Commençons par une définition claire de chaque type de texture que nous allons utiliser. Ce document, que vous connaissez déjà, les présente de manière concise.
Lisez la section intitulée « Les autres types de textures ». Concentrez-vous sur les définitions de normalMap, aoMap, metalnessMap, et roughnessMap. Notez bien qu'elles sont principalement utilisées avec les matériaux PBR comme le MeshStandardMaterial que nous utilisons déjà.
La normalMap : L'illusion du relief
La normalMap est peut-être la plus impressionnante. C'est une texture de couleur (souvent bleutée/violette) qui n'est pas destinée à être vue directement. Chaque pixel de cette image indique au moteur de rendu comment la lumière doit rebondir, créant une illusion de relief très détaillée sur une surface qui est en réalité parfaitement lisse. C'est une technique d'optimisation fondamentale : on obtient l'apparence d'un modèle très complexe pour le coût d'un modèle simple.
Cet article vous donnera plus de détails sur son fonctionnement.
Qu'est-ce qu'une carte normale - Danthree Studio
Pour bien comprendre la 'magie' de la normalMap, cet article du Danthree Studio offre une excellente explication visuelle.
Lisez les sections « Définition de la carte normale » et « Comment fonctionne exactement une carte normale ? ». L'idée clé est que les valeurs de couleur (RGB) de la texture sont interprétées comme des coordonnées de direction (XYZ) pour la normale de surface. Parcourez ensuite la FAQ à la fin, en particulier la question « Quels sont les emplacements de map que je dois occuper dans le matériel WebGL/Three.js ? », qui fait le lien direct avec notre code.
La roughnessMap : Le jeu des reflets
La roughnessMap (carte de rugosité) est une texture en niveaux de gris.
- Les zones noires (
valeur = 0) indiquent une surface parfaitement lisse, comme un miroir. - Les zones blanches (
valeur = 1) indiquent une surface très rugueuse, qui diffuse la lumière, comme du béton brut.
En utilisant une image avec des nuances de gris, on peut précisément contrôler quelles parties d'un objet sont brillantes (une flaque d'eau sur une route) et lesquelles sont mates (l'asphalte sec autour).
La aoMap : L'ombre qui donne du poids
aoMap signifie Ambient Occlusion Map. C'est également une texture en niveaux de gris qui stocke des informations d'ombrage pré-calculées. Elle assombrit les zones où la lumière ambiante a du mal à pénétrer : les fissures, les creux, ou le point de contact entre deux objets. Cela donne l'impression que l'objet est mieux "ancré" dans son environnement et ajoute une grande sensation de profondeur.
La vidéo suivante explique très bien ce concept.
From Blender to Three.js: The Complete Baking Guide (AO, PBR, High→Low Poly)
L'occlusion ambiante peut sembler abstraite, mais cette vidéo l'illustre parfaitement avec une analogie simple et montre le résultat visuel.
Regardez la séquence de 18:36 à 19:16. L'auteur explique le principe de l'occlusion ambiante ('la saleté qui va dans les creux') et donne une excellente analogie avec les angles des murs chez vous. Concentrez-vous sur le concept et le résultat visuel, pas sur le processus de création dans Blender.
Atelier : Appliquons nos textures PBR
Il est temps de mettre tout cela en pratique. Nous allons télécharger un jeu de textures PBR et les appliquer à un objet dans notre scène.
1. Trouver des textures PBR
De nombreux sites proposent des textures PBR gratuites et de haute qualité. Un excellent point de départ est AmbientCG. Cherchez un matériau qui vous plaît (par exemple "Rock", "Wood", "Metal"). Pour cet atelier, je vous suggère de télécharger le matériau Rock030 en résolution 2K-JPG. Vous obtiendrez un fichier ZIP contenant plusieurs images (Color, NormalGL, Roughness, AmbientOcclusion, etc.).
2. Préparer le projet
- Décompressez le fichier ZIP.
- Dans votre projet Vite, créez un dossier
public/textures/rock. - Copiez les images
Rock030_2K-JPG_Color.jpg,Rock030_2K-JPG_NormalGL.jpg,Rock030_2K-JPG_Roughness.jpgetRock030_2K-JPG_AmbientOcclusion.jpgdans ce dossier. Vous pouvez les renommer pour plus de simplicité (ex:color.jpg,normal.jpg,roughness.jpg,ao.jpg).
3. Coder dans Three.js
La vidéo suivante montre exactement comment charger et appliquer une normalMap et une roughnessMap. Nous ferons de même et ajouterons l'aoMap.
Cette vidéo concise montre comment assigner les propriétés normalMap et roughnessMap à un matériau. Suivez ce modèle pour notre atelier.
Regardez la séquence de 05:26 à 08:20. L'auteur charge plusieurs textures et les applique aux propriétés correspondantes du MeshStandardMaterial. Observez bien l'effet visuel de chaque carte, d'abord séparément, puis ensemble. C'est ce que nous allons reproduire.
Maintenant, à vous de jouer. Modifiez votre code main.js :
import * as THREE from 'three';
// ... autres imports
// ... setup scène, caméra, renderer, lumières ...
// 1. Charger toutes les textures
const textureLoader = new THREE.TextureLoader();
const colorMap = textureLoader.load('/textures/rock/color.jpg');
const aoMap = textureLoader.load('/textures/rock/ao.jpg');
const normalMap = textureLoader.load('/textures/rock/normal.jpg');
const roughnessMap = textureLoader.load('/textures/rock/roughness.jpg');
// 2. Créer la géométrie et le matériau
const geometry = new THREE.SphereGeometry(1, 64, 64);
const material = new THREE.MeshStandardMaterial({
map: colorMap,
normalMap: normalMap,
roughnessMap: roughnessMap,
aoMap: aoMap,
aoMapIntensity: 1 // On peut ajuster l'intensité de l'AO
});
// --- POINT TRÈS IMPORTANT ---
// Pour que l'aoMap fonctionne, la géométrie doit avoir un deuxième jeu de coordonnées UV (uv2).
// Les géométries de base de Three.js en ont, mais il faut les activer.
geometry.setAttribute('uv2', new THREE.BufferAttribute(geometry.attributes.uv.array, 2));
// 3. Créer le Mesh et l'ajouter à la scène
const sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);
// ... boucle d'animation ...
Expérimentez ! Une fois que cela fonctionne, essayez de commenter les lignes normalMap, roughnessMap et aoMap une par une pour bien voir la contribution de chaque texture au résultat final. Vous pouvez aussi jouer avec les propriétés material.aoMapIntensity ou material.normalScale.set(0.5, 0.5) pour moduler leur effet.
Et dans React Three Fiber ?
Votre but étant de maîtriser R3F, il est rassurant de savoir que ces concepts s'y appliquent directement. En R3F, on utilise souvent des modèles 3D (au format glTF/GLB) qui ont déjà toutes ces textures intégrées. L'avantage est que l'on n'a pas à charger et assigner chaque carte manuellement.
La vidéo ci-dessous montre l'utilisation d'un tel modèle dans un projet R3F.
From Blender to Three.js: The Complete Baking Guide (AO, PBR, High→Low Poly)
Pour faire le pont avec votre objectif final, regardons comment on utilise un modèle contenant déjà une aoMap dans un projet React Three Fiber.
Regardez la séquence de 23:33 à 25:42. L'auteur charge un modèle 3D complet (fichier .glb) qui a été exporté depuis Blender. Remarquez que le modèle a déjà son apparence réaliste grâce à l'occlusion ambiante intégrée. Il montre aussi qu'il est toujours possible de manipuler ses propriétés, comme la couleur, de manière déclarative avec JSX. Nous verrons en détail comment charger des modèles plus tard dans le cours.
Cela vous donne un aperçu de la puissance et de la simplicité de l'écosystème R3F, qui s'appuie sur toutes les connaissances fondamentales de Three.js que vous êtes en train d'acquérir.
Conclusion
Félicitations ! Vous avez fait un bond de géant en termes de réalisme. Vous savez maintenant que pour créer un matériau crédible, la couleur ne suffit pas. Il faut décrire ses propriétés physiques à l'aide de plusieurs textures spécialisées.
Points clés à retenir :
- Le PBR utilise plusieurs textures pour simuler la physique de la lumière sur les matériaux.
- La
normalMapajoute des détails de surface (relief) de manière très performante. - La
roughnessMapcontrôle la brillance et les reflets de la surface. - L'
aoMapajoute des ombres de contact qui donnent de la profondeur et ancrent les objets. - Pour que l'
aoMapfonctionne, il faut un deuxième jeu de coordonnées UV (uv2) sur la géométrie.
Aperçu de la prochaine leçon :
Nos objets ont maintenant une apparence de surface réaliste, mais notre éclairage global reste un peu générique. Pour que les reflets sur nos matériaux brillants soient crédibles, il faut qu'ils aient quelque chose à refléter ! Dans la prochaine leçon, nous apprendrons à mettre en place un éclairage basé sur l'image (IBL) en chargeant un environnement HDRI. Cela créera un éclairage et des reflets ultra-réalistes, comme si notre objet était réellement dans une scène photographiée.