Première scène
Créer le projet avec Vite, poser une scène, une caméra et un rendu, puis faire tourner un cube qui suit la taille de la fenêtre.
import * as THREE from "three";
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
0.1,
100,
);
camera.position.z = 5;
const renderer = new THREE.WebGLRenderer({
antialias: true,
});
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const cube = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshNormalMaterial(),
);
scene.add(cube);
renderer.setAnimationLoop((time) => {
cube.rotation.x = time / 1000;
cube.rotation.y = time / 1500;
renderer.render(scene, camera);
});
window.addEventListener("resize", () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
Créer le projet
On travaille avec Vite : un petit serveur qui recharge la page à chaque enregistrement et qui sait importer three depuis node_modules. Dans un terminal, crée le dossier du projet puis installe les deux paquets :
mkdir mon-projet
cd mon-projet
npm init -y
npm install three
npm install --save-dev viteOuvre ensuite package.json et ajoute la ligne "type": "module" ainsi qu’un script dev :
{
"type": "module",
"scripts": {
"dev": "vite"
}
}Crée enfin les deux fichiers de la démo, index.html et main.js, à la racine du dossier (leur code complet est juste au-dessus, dans les onglets de la démo), puis lance :
npm run devVite affiche une adresse du type http://localhost:5173 : ouvre-la dans le navigateur. Laisse ce terminal ouvert pendant que tu codes.
Le style de index.html enlève la marge du body et passe le canvas en bloc : sans lui, des barres de défilement apparaissent autour de la scène.
Les trois indispensables
Toute scène Three.js repose sur trois objets : la scène (ce qu’on montre), la caméra (d’où on regarde) et le rendu (qui dessine l’image dans un canvas).
La scène
import * as THREE from "three";
const scene = new THREE.Scene();La première ligne importe toute la bibliothèque sous le nom THREE. La scène est une boîte vide : on y ajoutera les objets, les lumières et les caméras.
La caméra
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
0.1,
100,
);
camera.position.z = 5;Les quatre réglages, dans l’ordre :
- l’angle de vue vertical, en degrés (45 donne un rendu naturel) ;
- le rapport largeur sur hauteur de l’image, ici celui de la fenêtre ;
- la distance minimale à laquelle un objet est encore dessiné ;
- la distance maximale.
Tout ce qui est plus près que 0.1 ou plus loin que 100 disparaît. La caméra naît au centre de la scène, comme le cube : on la recule de 5 unités sur l’axe z pour voir le cube de face.
Le rendu
const renderer = new THREE.WebGLRenderer({
antialias: true,
});
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);antialias lisse les bords des objets. setPixelRatio rend l’image nette sur les écrans Retina, sans dépasser 2 pour ne pas faire chauffer les téléphones. renderer.domElement est le canvas créé par Three.js : on l’ajoute à la page.
Ajouter un objet
Un objet visible s’appelle un mesh : une géométrie (la forme) et un matériau (l’aspect).
const cube = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshNormalMaterial(),
);
scene.add(cube);MeshNormalMaterial colore chaque face selon son orientation : il n’a pas besoin de lumière, c’est parfait pour vérifier que tout marche. Pour un matériau qui réagit à la lumière, va voir la doc « Lumières, ombres et réglages ».
La boucle d’animation
renderer.setAnimationLoop((time) => {
cube.rotation.x = time / 1000;
cube.rotation.y = time / 1500;
renderer.render(scene, camera);
});La fonction passée à setAnimationLoop est appelée à chaque image (60 fois par seconde environ). time donne le nombre de millisecondes depuis le lancement : en le divisant, on obtient une rotation en radians qui avance doucement. Chaque tour de boucle se termine par renderer.render(scene, camera), qui dessine l’image.
Suivre la taille de la fenêtre
window.addEventListener("resize", () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});Quand la fenêtre change de taille, on met à jour le rapport de la caméra puis on recalcule sa projection avec updateProjectionMatrix() (sans cet appel, le changement n’est pas pris en compte), et on redimensionne le canvas.
Si l’écran reste noir, ouvre la console du navigateur (clic droit, Inspecter, onglet Console) : une faute de frappe dans un import ou un nom de classe y est toujours signalée.
Pour aller plus loin
- Remplace
BoxGeometryparSphereGeometry(0.7, 32, 16)ouTorusKnotGeometry(0.5, 0.18, 128, 16). - Change
camera.position.zet regarde ce que ça fait. - La documentation de Three.js liste toutes les géométries et tous les matériaux.