Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 34

JSX pour des Objets Three.js Déclaratifs

Recommended resources

Bonjour !

Dans la leçon précédente, nous avons posé les fondations de notre application en initialisant un projet React Three Fiber (R3F) avec le composant <Canvas>. Vous avez vu que ce composant unique nous évite toute la configuration manuelle d'une scène, d'une caméra et d'une boucle de rendu. Notre "scène de théâtre" est prête, mais elle est vide.

Aujourd'hui, nous allons faire entrer les acteurs. L'objectif est d'apprendre à déclarer des objets Three.js de manière déclarative en utilisant la syntaxe JSX. C'est ici que la magie de R3F opère vraiment, en vous permettant de construire une scène 3D avec une syntaxe qui vous est déjà familière en tant que développeur React.

1. Le paradigme déclaratif de R3F

Rappelez-vous, en Three.js "pur", pour créer un simple cube, nous devions écrire du code impératif, une série d'ordres :

// L'approche impérative de Three.js
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 'red' });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

Avec R3F, nous passons à une approche déclarative. Au lieu de dire comment créer le cube, nous allons décrire le cube que nous voulons voir.

// L'approche déclarative de React Three Fiber
<mesh>
  <boxGeometry args={[1, 1, 1]} />
  <meshBasicMaterial color="red" />
</mesh>

La règle est simple : la plupart des classes de Three.js (comme Mesh, BoxGeometry, MeshBasicMaterial) deviennent des composants JSX. Il suffit de prendre le nom de la classe et de le mettre en "camelCase" avec une minuscule au début.

React Three Fiber vs. Three.js Object Declaration
Ce comparatif illustre parfaitement la concision et la lisibilité du code R3F (à gauche) par rapport au code Three.js impératif (à droite) pour un résultat identique.

2. Les briques élémentaires : Géométrie et Matériau

Tout objet visible dans une scène 3D, appelé Mesh, est la combinaison de deux éléments fondamentaux :

  1. La Géométrie (Geometry) : C'est la structure, le "squelette" de l'objet. Elle définit sa forme (un cube, une sphère, un tore, etc.).
  2. Le Matériau (Material) : C'est l'apparence, la "peau" de l'objet. Il définit sa couleur, sa texture, et comment il réagit à la lumière (brillant, mat, métallique...).
Composition of a 3D Mesh
Ce diagramme simple montre qu'un `Mesh` est toujours le résultat de l'association d'une `Geometry` (la forme) et d'un `Material` (l'apparence).

Pour approfondir cette nouvelle syntaxe, la ressource suivante est un excellent guide pratique.

React Three Fiber Crash Course for Beginners

Cette section de la vidéo "React Three Fiber Crash Course for Beginners" par Wael Yasmina est parfaite pour notre objectif. Elle montre concrètement comment déclarer différentes géométries et matériaux en JSX.

Regardez la vidéo de 03:46 à 07:33. Ne vous préoccupez pas de recopier le code pour l'instant, concentrez-vous sur les concepts suivants : Comment un <mesh> est composé d'une géométrie (ex: <sphereGeometry>) et d'un matériau (ex: <meshBasicMaterial>). La différence entre meshBasicMaterial (qui n'est pas affecté par la lumière) et meshPhongMaterial ou meshToonMaterial (qui nécessitent une source de lumière pour être visibles). Comment les propriétés des objets sont passées via des props React.


3. Passer des propriétés avec les props

Comme vous l'avez vu dans la vidéo, nous utilisons les props pour configurer nos objets, tout comme avec des composants React classiques. Il y a quelques conventions importantes à connaître.

Props directes

Les propriétés simples comme la couleur ou le mode "fil de fer" (wireframe) se passent directement. R3F est assez intelligent pour comprendre différents formats.

// La couleur peut être un nom, un code hexa, ou un objet THREE.Color
<meshBasicMaterial color="orange" />
<meshBasicMaterial color="#ff0000" />

// Les booléens fonctionnent comme attendu
<meshBasicMaterial color="lightblue" wireframe={true} />

La prop args

C'est l'une des props les plus importantes de R3F. Lorsque vous créez un objet en Three.js avec new MaClasse(arg1, arg2, ...) , ces arguments du constructeur sont passés dans R3F via la prop args, qui attend un tableau.

// En Three.js
const geometry = new THREE.BoxGeometry(2, 3, 4); // width, height, depth

// En R3F
<boxGeometry args={[2, 3, 4]} />

C'est ainsi que vous définissez la taille d'une boîte, le rayon d'une sphère, etc.

La prop attach

Comment un composant <boxGeometry /> "sait-il" qu'il doit devenir la géométrie de son parent <mesh /> ? Grâce à la prop attach. Dans la plupart des cas, R3F le déduit pour vous : une géométrie s'attache à la propriété geometry du parent, un matériau à la propriété material. Vous n'avez donc généralement pas besoin de l'écrire.

// Version explicite avec 'attach'
<mesh>
  <boxGeometry attach="geometry" args={[1, 1, 1]} />
  <meshStandardMaterial attach="material" color="hotpink" />
</mesh>

// Version implicite (et plus courante)
<mesh>
  <boxGeometry args={[1, 1, 1]} />
  <meshStandardMaterial color="hotpink" />
</mesh>

Les deux sont équivalents !

Pour une référence textuelle en français qui résume bien ces concepts, vous pouvez consulter l'article suivant.

Qu'est-ce que React Three Fiber? - Wawa Sensei

L'article "Qu'est-ce que React Three Fiber?" de Wawa Sensei offre un excellent résumé de la philosophie de R3F et une comparaison de code claire.

Lisez les sections "React Three Fiber" et l'exemple de code qui suit. Cela renforcera votre compréhension de la transition du code impératif vers le code déclaratif.


4. Positionner les objets dans l'espace

Créer un objet, c'est bien. Le placer où l'on veut, c'est mieux ! Les transformations de base se font également via des props sur le composant <mesh>.

  • position: Déplace l'objet sur les axes x, y, z.
  • rotation: Fait pivoter l'objet. Les valeurs sont en radians.
  • scale: Change la taille de l'objet.
<mesh position={[2, 0, 0]} /* Déplacé de 2 unités sur l'axe X */ >
  {/* ... */}
</mesh>

<mesh rotation={[0, Math.PI / 4, 0]} /* Pivoté de 45 degrés sur l'axe Y */ >
  {/* ... */}
</mesh>

<mesh scale={2} /* Deux fois plus grand sur tous les axes */ >
  {/* ... */}
</mesh>

Vous pouvez aussi spécifier un seul axe, par exemple position-x={2}.

La vidéo que vous avez commencée tout à l'heure couvre également ce point.

React Three Fiber Crash Course for Beginners

Continuons avec la vidéo de Wael Yasmina pour voir comment appliquer ces transformations.

Regardez la section de 07:33 à 08:20. L'auteur y montre comment utiliser les props position, rotation et scale.


Atelier : Votre première nature morte

Il est temps de mettre tout cela en pratique. Repartez du projet que vous aviez à la fin de la leçon précédente (avec le <Canvas> en plein écran).

Votre mission :

  1. Ajoutez de la lumière. Les matériaux comme meshStandardMaterial en ont besoin pour être visibles. Ajoutez ces deux lignes à l'intérieur de votre <Canvas> :

    <ambientLight intensity={0.5} />
    <directionalLight position={[10, 10, 5]} intensity={1} />
    

    Nous étudierons les lumières en détail plus tard. Pour l'instant, considérez-les comme nécessaires pour éclairer la scène.

  2. Créez trois objets distincts :

    • Une sphère rouge, utilisant <sphereGeometry /> et <meshStandardMaterial />.
    • Un cube bleu, utilisant <boxGeometry /> et <meshStandardMaterial />.
    • Un tore (un donut) vert, utilisant <torusGeometry /> et <meshStandardMaterial />.
  3. Positionnez-les pour qu'ils ne se superposent pas. Par exemple :

    • Le cube au centre [0, 0, 0].
    • La sphère à gauche [-2, 0, 0].
    • Le tore à droite [2, 0, 0].
  4. (Bonus) Utilisez la prop scale pour que le tore soit moitié moins grand que les autres objets.

Voici à quoi pourrait ressembler votre composant App.jsx une fois terminé :

import { Canvas } from '@react-three/fiber'

function App() {
  return (
    <Canvas>
      {/* Lumières */}
      <ambientLight intensity={0.5} />
      <directionalLight position={[10, 10, 5]} intensity={1} />

      {/* Cube au centre */}
      <mesh position={[0, 0, 0]}>
        <boxGeometry args={[1, 1, 1]} />
        <meshStandardMaterial color="blue" />
      </mesh>

      {/* Sphère à gauche */}
      <mesh position={[-2, 0, 0]}>
        <sphereGeometry args={[0.7, 32, 32]} />
        <meshStandardMaterial color="red" />
      </mesh>
      
      {/* Tore à droite, plus petit */}
      <mesh position={[2, 0, 0]} scale={0.5}>
        <torusGeometry args={[0.5, 0.2, 32, 100]} />
        <meshStandardMaterial color="green" />
      </mesh>
    </Canvas>
  )
}

export default App

Conclusion

Félicitations ! Vous venez de franchir une étape majeure. Vous savez maintenant comment traduire les concepts de base de Three.js (mesh, géométrie, matériau) en une syntaxe JSX propre, lisible et réutilisable, au cœur de la philosophie de React.

Points clés à retenir :

  • R3F utilise des composants JSX déclaratifs pour représenter les objets Three.js (ex: <mesh>).
  • Un Mesh est composé d'une Géométrie (la forme, ex: <boxGeometry>) et d'un Matériau (l'apparence, ex: <meshStandardMaterial>).
  • Les arguments du constructeur d'une classe Three.js sont passés via la prop args={[...]} .
  • Les propriétés simples (comme color) et les transformations (position, rotation, scale) sont passées comme des props classiques.

Aperçu de la prochaine leçon :
Nos objets sont beaux, mais statiques. Comment leur donner vie ? Dans la prochaine leçon, nous allons découvrir le hook useFrame, l'équivalent R3F de la boucle d'animation. C'est le moteur qui vous permettra de créer des animations fluides et des interactions dynamiques.