iducationducation
IndexArticlesFormationsProfilOutilsBibliothech
N°014 — 2026
Navigation
01Index02Articles03Formations04Profil05Outils06Bibliothech
N°014 — 2026
iducationducation
IndexArticlesFormationsProfilOutilsBibliothech
N°014 — 2026
Navigation
01Index02Articles03Formations04Profil05Outils06Bibliothech
N°014 — 2026
Formations
JavaScript · Intermédiaire

Three.js

Créer de la 3D dans le navigateur de zéro : scène, modèles STL/GLTF, animation au scroll, shaders, post-processing et portfolio 3D animé complet.

Three.jsJavaScriptGSAPGLSLWebGL
01Introduction à Three.js02Géométries, matériaux et lumières03Charger des modèles 3D — STL et GLTF04Animer au scroll — Three.js + GSAP05Post-processing et effets visuels06Shaders GLSL et systèmes de particules07Portfolio 3D animé — projet complet
Chapitre 2·25 min

Géométries, matériaux et lumières

Three.js a des dizaines de géométries et matériaux intégrés. Comprendre quand utiliser lequel — et comment les lumières interagissent — permet de construire des scènes rapidement sans aller chercher des modèles 3D pour chaque élément.

Géométries

Toutes les géométries Three.js héritent de BufferGeometry. Elles stockent les positions des vertices, les normales (direction des surfaces pour l'éclairage), les UV (coordonnées de texture) et les indices (triangles) dans des buffers GPU.

Primitives courantes

// Cube
new THREE.BoxGeometry(1, 1, 1)
// BoxGeometry(width, height, depth, widthSegments, heightSegments, depthSegments)
// Les segments divisent les faces — utile pour les déformations
 
// Sphère
new THREE.SphereGeometry(0.5, 32, 32)
// SphereGeometry(radius, widthSegments, heightSegments)
// Plus de segments = plus rond, plus coûteux
 
// Plan
new THREE.PlaneGeometry(2, 2, 1, 1)
 
// Cylindre
new THREE.CylinderGeometry(0.5, 0.5, 1, 32)
// CylinderGeometry(radiusTop, radiusBottom, height, radialSegments)
 
// Tore (donut)
new THREE.TorusGeometry(0.4, 0.15, 16, 100)
 
// Tore noué
new THREE.TorusKnotGeometry(0.4, 0.1, 100, 16)
 
// Icosaèdre — base pour les sphères low-poly
new THREE.IcosahedronGeometry(0.5, 0)  // detail = 0 → low poly
new THREE.IcosahedronGeometry(0.5, 4)  // detail = 4 → quasi-sphère

BufferGeometry custom

Pour des formes personnalisées, on construit la géométrie à partir de vertices.

const geometry = new THREE.BufferGeometry()
 
// 3 vertices = 1 triangle
const vertices = new Float32Array([
  -1, -1, 0,  // vertex 0 : x, y, z
   1, -1, 0,  // vertex 1
   0,  1, 0,  // vertex 2
])
 
geometry.setAttribute(
  'position',
  new THREE.BufferAttribute(vertices, 3)  // 3 valeurs par vertex
)
 
geometry.computeVertexNormals()  // calculer les normales pour l'éclairage

Pour des milliers de triangles, Float32Array est directement transféré au GPU — pas de conversion.

Matériaux

MeshBasicMaterial

Pas d'éclairage. La couleur est constante quelle que soit la lumière. Utile pour les wireframes et les éléments qui ne doivent pas être affectés par la lumière.

const mat = new THREE.MeshBasicMaterial({
  color: '#ff0000',
  wireframe: true,   // afficher seulement les arêtes
})

MeshStandardMaterial

Le matériau par défaut pour la plupart des cas. PBR — réagit aux lumières de façon physiquement correcte.

const mat = new THREE.MeshStandardMaterial({
  color: '#888888',
  roughness: 0.5,    // 0 = miroir, 1 = totalement mat
  metalness: 0.0,    // 0 = non-métallique, 1 = métal pur
  envMapIntensity: 1, // intensité du reflet d'environnement
})

MeshPhysicalMaterial

Extension de MeshStandardMaterial avec des propriétés supplémentaires pour des matériaux complexes.

const glass = new THREE.MeshPhysicalMaterial({
  color: '#ffffff',
  roughness: 0,
  metalness: 0,
  transmission: 1.0,    // transparence physique (verre)
  thickness: 0.5,       // épaisseur pour la réfraction
  ior: 1.5,             // index of refraction (verre = 1.5)
  transparent: true,
})
 
const clearcoat = new THREE.MeshPhysicalMaterial({
  color: '#cc0000',
  roughness: 0.3,
  metalness: 0.8,
  clearcoat: 1.0,         // vernis brillant par-dessus
  clearcoatRoughness: 0.1,
})

MeshNormalMaterial

Affiche les normales des surfaces en couleur — rouge = X, vert = Y, bleu = Z. Utile pour déboguer.

const mat = new THREE.MeshNormalMaterial()

ShaderMaterial

Shaders GLSL entièrement custom. Couvert au chapitre 6.

Textures

Charger une texture

const textureLoader = new THREE.TextureLoader()
 
const colorMap = textureLoader.load('/textures/wood_color.jpg')
const roughnessMap = textureLoader.load('/textures/wood_roughness.jpg')
const normalMap = textureLoader.load('/textures/wood_normal.jpg')
 
const mat = new THREE.MeshStandardMaterial({
  map: colorMap,              // texture de couleur (albedo)
  roughnessMap: roughnessMap, // rugosité par zone
  normalMap: normalMap,       // simulation de relief (sans polygones)
  normalScale: new THREE.Vector2(1, 1),
})

Répétition et wrapping

colorMap.wrapS = THREE.RepeatWrapping  // axe horizontal
colorMap.wrapT = THREE.RepeatWrapping  // axe vertical
colorMap.repeat.set(4, 4)             // répéter 4x dans chaque direction

Environment map — reflets HDR

Un HDRI (image 360° haute dynamique) sert de source de lumière et de reflet pour les matériaux PBR.

import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js'
 
const rgbeLoader = new RGBELoader()
rgbeLoader.load('/hdri/studio.hdr', (texture) => {
  texture.mapping = THREE.EquirectangularReflectionMapping
 
  scene.environment = texture  // utilisé pour les reflets de TOUS les matériaux
  scene.background = texture   // aussi comme arrière-plan (optionnel)
})

Avec un HDRI, même une sphère métallique sans lumières directionnelles est visuellement convaincante — les reflets de l'environnement font tout le travail.

Lumières

AmbientLight

Éclairage de base sans direction. Éclaire uniformément tout dans la scène.

const ambient = new THREE.AmbientLight('#ffffff', 0.3)
scene.add(ambient)

Ne pas mettre trop fort — ça "aplatit" la scène en annulant les ombres et contrastes.

DirectionalLight

Simule le soleil — rayons parallèles depuis une direction.

const dirLight = new THREE.DirectionalLight('#ffffff', 2)
dirLight.position.set(5, 10, 5)  // direction = de cette position vers l'origine
 
// Ombres
dirLight.castShadow = true
dirLight.shadow.mapSize.width = 2048   // résolution de la shadow map
dirLight.shadow.mapSize.height = 2048
dirLight.shadow.camera.near = 0.1
dirLight.shadow.camera.far = 50
dirLight.shadow.camera.left = -10
dirLight.shadow.camera.right = 10
dirLight.shadow.camera.top = 10
dirLight.shadow.camera.bottom = -10
dirLight.shadow.bias = -0.001  // évite le "shadow acne" (artefacts)
 
scene.add(dirLight)

Pour les ombres : renderer.shadowMap.enabled = true, mesh.castShadow = true, planeSol.receiveShadow = true.

PointLight

Lumière en point — comme une ampoule. Rayonne dans toutes les directions, s'atténue avec la distance.

const pointLight = new THREE.PointLight('#ff6600', 5, 10)
// PointLight(color, intensity, distance)
pointLight.position.set(2, 3, 2)
scene.add(pointLight)

SpotLight

Cone de lumière avec angle et pénombre.

const spot = new THREE.SpotLight('#ffffff', 10)
spot.position.set(0, 10, 0)
spot.angle = Math.PI / 6   // angle du cone (30°)
spot.penumbra = 0.3         // douceur du bord (0 = dur, 1 = très doux)
spot.target.position.set(0, 0, 0)
scene.add(spot)
scene.add(spot.target)  // le target doit aussi être dans la scène

RectAreaLight

Surface lumineuse rectangulaire — comme un panneau lumineux ou une fenêtre.

import { RectAreaLightHelper } from 'three/examples/jsm/helpers/RectAreaLightHelper.js'
import { RectAreaLightUniformsLib } from 'three/examples/jsm/lights/RectAreaLightUniformsLib.js'
 
RectAreaLightUniformsLib.init()  // obligatoire pour RectAreaLight
 
const rectLight = new THREE.RectAreaLight('#ffffff', 5, 4, 2)
// RectAreaLight(color, intensity, width, height)
rectLight.position.set(0, 5, -5)
rectLight.lookAt(0, 0, 0)
scene.add(rectLight)

RectAreaLight fonctionne uniquement avec MeshStandardMaterial et MeshPhysicalMaterial. Elle ne supporte pas les ombres (limitation WebGL).

Helpers de debug

Pendant le développement, les helpers visualisent les éléments invisibles.

import { DirectionalLightHelper } from 'three'
import { CameraHelper } from 'three'
 
// Voir la position et direction d'une lumière
const lightHelper = new THREE.DirectionalLightHelper(dirLight, 1)
scene.add(lightHelper)
 
// Voir le frustum de la shadow camera
const shadowHelper = new THREE.CameraHelper(dirLight.shadow.camera)
scene.add(shadowHelper)
 
// Axes X Y Z
const axesHelper = new THREE.AxesHelper(5)
scene.add(axesHelper)
 
// Grille au sol
const gridHelper = new THREE.GridHelper(20, 20)
scene.add(gridHelper)

Toujours les retirer avant la mise en production.

Optimisation : partager géométries et matériaux

Une géométrie et un matériau peuvent être partagés par plusieurs meshes — le GPU charge les données une seule fois.

const sharedGeo = new THREE.SphereGeometry(0.2, 16, 16)
const sharedMat = new THREE.MeshStandardMaterial({ color: '#cdff4f' })
 
// 100 sphères avec la même géo et le même mat
for (let i = 0; i < 100; i++) {
  const mesh = new THREE.Mesh(sharedGeo, sharedMat)
  mesh.position.set(
    (Math.random() - 0.5) * 20,
    (Math.random() - 0.5) * 20,
    (Math.random() - 0.5) * 20
  )
  scene.add(mesh)
}

Pour des centaines ou milliers d'instances identiques, InstancedMesh est encore plus performant — un seul draw call pour toutes les instances.


Géométries, matériaux, textures, lumières — la boîte à outils est complète. Le chapitre suivant couvre le point crucial du cours : charger des modèles 3D réels (STL, GLTF) et les intégrer dans la scène.

Précédent
Introduction à Three.js
Suivant
Charger des modèles 3D — STL et GLTF

Développeur fullstack passionné. J'apprends en construisant et je documente tout — front, back, outils. Le code s'apprend mieux en public.

Naviguer

IndexTous les articlesFormationsProfilOutilsBibliothech

Ailleurs

GitHub RSS

Newsletter

Les articles, libs et découvertes. Une fois par semaine, pas plus.

© 2026 William LoreeConçu & codé à la main