fundamentals.html 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. <!DOCTYPE html><html lang="fr"><head>
  2. <meta charset="utf-8">
  3. <title>principes de base</title>
  4. <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
  5. <meta name="twitter:card" content="summary_large_image">
  6. <meta name="twitter:site" content="@threejs">
  7. <meta name="twitter:title" content="Three.js – principes de base">
  8. <meta property="og:image" content="https://threejs.org/files/share.png">
  9. <link rel="shortcut icon" href="../../files/favicon_white.ico" media="(prefers-color-scheme: dark)">
  10. <link rel="shortcut icon" href="../../files/favicon.ico" media="(prefers-color-scheme: light)">
  11. <link rel="stylesheet" href="../resources/lesson.css">
  12. <link rel="stylesheet" href="../resources/lang.css">
  13. <script type="importmap">
  14. {
  15. "imports": {
  16. "three": "../../build/three.module.js"
  17. }
  18. }
  19. </script>
  20. </head>
  21. <body>
  22. <div class="container">
  23. <div class="lesson-title">
  24. <h1>principes de base</h1>
  25. </div>
  26. <div class="lesson">
  27. <div class="lesson-main">
  28. <p>Ceci est le premier article d'une série consacrée à Three.js.
  29. <a href="https://threejs.org">Three.js</a> est une bibliothèque 3D qui a pour objectif
  30. de rendre aussi facile que possible l'inclusion de contenu 3D dans une page web.</p>
  31. <p>Three.js est souvent confondu avec WebGL puisque la plupart du temps, mais
  32. pas toujours, elle exploite WebGL pour dessiner en 3D.
  33. <a href="https://webglfundamentals.org">WebGL est un système très bas niveau qui ne dessine que des points, des lignes et des triangles</a>.
  34. Faire quelque chose d'exploitable avec WebGL requiert une certaine quantité de code
  35. et c'est là que Three.js intervient. Elle prend en charge des choses
  36. telles que les scènes, lumières, ombres, matériaux, textures, mathématiques 3D, en bref,
  37. tout ce que vous avez à écrire par vous même si vous aviez à utiliser WebGL directement.</p>
  38. <p>Ces tutoriels supposent que JavaScript vous est connu et, pour grande partie,
  39. se conforment au style ES6. <a href="prerequisites.html">Consultez ici une brève liste des choses que vous êtes
  40. déjà censés connaître</a>.</p>
  41. <p>La plupart des navigateurs qui supportent three.js se mettent à jour automatiquement
  42. donc la plupart des utilisateurs devraient être capables d'exécuter ce code.
  43. Si vous souhaitez exécuter ce code sur un très vieux navigateur, nous vous recommandons
  44. un transpileur tel que <a href="https://babeljs.io">Babel</a>.
  45. Bien sûr, les utilisateurs exécutant de très vieux navigateurs ont probablement
  46. des machines incapables de faire tourner Three.js.</p>
  47. <p>Lors de l'apprentissage de la plupart des langages de programmation,
  48. la première tâche que les gens font est de faire afficher à l'ordinateur
  49. <code class="notranslate" translate="no">"Hello World!"</code>. Pour la programmation 3D, l'équivalent est de faire afficher
  50. un cube en 3D. Donc, nous commencerons par "Hello Cube!".</p>
  51. <p>Avant de débuter, nous allons tenter de vous donner un idée de la structure
  52. d'une application Three.js. Elle requiert de créer un ensemble d'objets
  53. et de les connecter. Voici un diagramme qui représente une application
  54. Three.js de petite taille:</p>
  55. <div class="threejs_center"><img src="../resources/images/threejs-structure.svg" style="width: 768px;"></div>
  56. <p>Voici ce qui est à remarquer dans le diagramme ci-dessus :</p>
  57. <ul>
  58. <li><p>Il y a un <a href="/docs/#api/en/constants/Renderer"><code class="notranslate" translate="no">Renderer</code></a>. C'est sans doute l'objet principal de Three.js. Vous passez
  59. une <a href="/docs/#api/en/scenes/Scene"><code class="notranslate" translate="no">Scene</code></a> et une <a href="/docs/#api/en/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a> à un <a href="/docs/#api/en/constants/Renderer"><code class="notranslate" translate="no">Renderer</code></a> et il effectue le rendu (dessine) de la
  60. partie de la scène 3D qui est à l'intérieur de l'espace visible (en réalité une pyramide tronquée ou <em>frustum</em>)
  61. de la caméra dans une image 2D affichée dans un canevas (<em>canvas</em>).</p>
  62. </li>
  63. <li><p>Il y a un <a href="scenegraph.html">graphe de scène</a> qui est une structure arborescente,
  64. constituée de divers objets tel qu'un objet <a href="/docs/#api/en/scenes/Scene"><code class="notranslate" translate="no">Scene</code></a>, de multiple maillages (<a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a>),
  65. des lumières (<a href="/docs/#api/en/lights/Light"><code class="notranslate" translate="no">Light</code></a>), des groupes (<a href="/docs/#api/en/objects/Group"><code class="notranslate" translate="no">Group</code></a>), des objets 3D <a href="/docs/#api/en/core/Object3D"><code class="notranslate" translate="no">Object3D</code></a> et des objets <a href="/docs/#api/en/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a>.
  66. Un objet <a href="/docs/#api/en/scenes/Scene"><code class="notranslate" translate="no">Scene</code></a> définit la racine d'un graphe de scène et contient des propriétés telles que
  67. la couleur d'arrière plan et le brouillard. L'ensemble de ces objets définissent une structure
  68. hiérarchique de type parent/enfant, arborescente, et indique où les objets apparaissent et
  69. comment ils sont orientés. Les enfants sont positionnés et orientés par rapport à leur parent.
  70. Par exemple, les roues d'une voiture sont les enfants du châssis impliquant que si l'on déplace
  71. ou oriente la voiture, les roues suivront automatiquement son déplacement. Plus de
  72. détails sont donnés dans <a href="scenegraph.html">l'article sur les graphes de scène</a>.</p>
  73. <p>Il est à noter sur que ce diagramme <a href="/docs/#api/en/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a> est patiellement placé dans le graphe de scène.
  74. Cela permet d'attirer l'attention qu'en Three.js, contrairement aux autres objets, une <a href="/docs/#api/en/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a> ne doit
  75. pas forcément faire partie du graphe de scène pour être opérationnelle. Une <a href="/docs/#api/en/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a>, de la même
  76. façon que les autres objets, enfant d'un autre objet, se déplace et s'oriente par rapport à son
  77. objet parent. A la fin de <a href="scenegraph.html">l'article sur les graphes de scène</a>, l'inclusion
  78. de multiples objets <a href="/docs/#api/en/cameras/Camera"><code class="notranslate" translate="no">Camera</code></a> dans un unique graphe de scène est donné en exemple.</p>
  79. </li>
  80. <li><p>Les objets de type <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> représentent une géométrie (<code class="notranslate" translate="no">Geometry</code>) liée à un matériau (<a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a>)
  81. spécifique. Les objets <a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a> et <code class="notranslate" translate="no">Geometry</code> peuvent être liés à plusieurs objets <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a>
  82. simultanément. Par exemple, pour dessiner deux cubes bleus à des positions différentes, nous
  83. pouvons soit utiliser deux objets <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> pour spécifier les positions et orientations de
  84. chaque cube; soit nous pouvons utiliser seulement une géométrie unique (<code class="notranslate" translate="no">Geometry</code>) pour décrire les
  85. données spatiales du cube et un matériau unique (<a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a>) pour spécifier la couleur bleue.
  86. Les deux objets <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> peuvent ainsi référencer les mêmes objets <code class="notranslate" translate="no">Geometry</code> et <a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a>.</p>
  87. </li>
  88. <li><p>Les objets <code class="notranslate" translate="no">Geometry</code> représentent les données associées aux sommets d'une géométrie telle qu'une
  89. sphère, un cube, un avion, un chien, un chat, un humain, un arbre, un bâtiment, etc...
  90. Three.js fournit plusieurs types intégrés de <a href="primitives.html">primitives géométriques</a>.
  91. Vous pouvez aussi <a href="custom-buffergeometry.html">créer vos propres géométries</a> ou
  92. <a href="load-obj.html">charger des géométries à partir d'un fichier</a>.</p>
  93. </li>
  94. <li><p>Les objets <a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a> représentent les
  95. <a href="materials.html">propriétés de surface utilisées pour dessiner la géométrie</a>
  96. telles que la couleur à utiliser ou le pouvoir réfléchissant (brillance). Un matériau (<a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a>)
  97. peut aussi se référer à un ou plusieurs objets <a href="/docs/#api/en/textures/Texture"><code class="notranslate" translate="no">Texture</code></a> dont l'utilité est, par exemple, de plaquer
  98. une image sur la surface d'une géométrie.</p>
  99. </li>
  100. <li><p>Les objets <a href="/docs/#api/en/textures/Texture"><code class="notranslate" translate="no">Texture</code></a> représentent généralement des images soit <a href="textures.html">chargées de fichiers image</a>,
  101. soit <a href="canvas-textures.html">générées par le biais d'un canevas</a> ou
  102. <a href="rendertargets.html">résultant du rendu d'une autre scène</a>.</p>
  103. </li>
  104. <li><p>Les objets <a href="/docs/#api/en/lights/Light"><code class="notranslate" translate="no">Light</code></a> représentent <a href="lights.html">différentes sortes de lumière</a>.</p>
  105. </li>
  106. </ul>
  107. <p>Maintenant que tout cela a été défini, nous allons présenter un exemple de type <em>"Hello Cube"</em> utilisant un
  108. nombre minimum d'élements Three.js :</p>
  109. <div class="threejs_center"><img src="../resources/images/threejs-1cube-no-light-scene.svg" style="width: 500px;"></div>
  110. <p>Tout d'abord, chargeons Three.js :</p>
  111. <pre class="prettyprint showlinemods notranslate lang-html" translate="no">&lt;script type="module"&gt;
  112. import * as THREE from 'three';
  113. &lt;/script&gt;
  114. </pre>
  115. <p>Il est important d'écrire <code class="notranslate" translate="no">type="module"</code> dans la balise script.
  116. Cela nous autorise l'utilisation du mot-clé <code class="notranslate" translate="no">import</code> pour charger Three.js.
  117. Il y a d'autres manières de le réaliser, mais depuis la version 106 (r106),
  118. l'utilisation des modules est recommandée. Ils ont l'avantage de pouvoir
  119. facilement importer les autres modules dont ils ont besoin. Cela nous
  120. épargne d'avoir à charger à la main les scripts supplémentaires dont ils dépendent.</p>
  121. <p>Ensuite, nous avons besoin d'une balise <code class="notranslate" translate="no">&lt;canvas&gt;</code> :</p>
  122. <pre class="prettyprint showlinemods notranslate lang-html" translate="no">&lt;body&gt;
  123. &lt;canvas id="c"&gt;&lt;/canvas&gt;
  124. &lt;/body&gt;
  125. </pre>
  126. <p>Nous allons demander à Three.js de dessiner dans ce canevas donc nous devons le rechercher
  127. dans le document html :</p>
  128. <pre class="prettyprint showlinemods notranslate lang-html" translate="no">&lt;script type="module"&gt;
  129. import * as THREE from 'three';
  130. +function main() {
  131. + const canvas = document.querySelector('#c');
  132. + const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
  133. + ...
  134. &lt;/script&gt;
  135. </pre>
  136. <p>Après la recherche du canevas, nous créons un <a href="/docs/#api/en/renderers/WebGLRenderer"><code class="notranslate" translate="no">WebGLRenderer</code></a>. Le <em>renderer</em>
  137. a pour mission de charger les données fournies et d'en effectuer le rendu
  138. dans le canevas.</p>
  139. <p>Notez qu'il y a quelques détails ésotériques ici. Si vous ne passez pas un
  140. canevas à Three.js, il va en créer un pour vous mais vous aurez à l'ajouter
  141. au document. Où l'ajouter peut dépendre du contexte d'utilisation et vous aurez
  142. à modifier votre code en conséquence. Passer un canevas à Three.js nous apparaît donc
  143. plus flexible. Nous pouvons mettre le canevas n'importe où et le code le retrouvera.
  144. Dans le cas contraire, nous aurons à coder où insérer le canevas, ce qui amènera
  145. probablement à changer le code si le contexte d'utilisation change.</p>
  146. <p>Ensuite, nous avons besoin d'une caméra. Nous créons une <a href="/docs/#api/en/cameras/PerspectiveCamera"><code class="notranslate" translate="no">PerspectiveCamera</code></a>.</p>
  147. <pre class="prettyprint showlinemods notranslate lang-js" translate="no">const fov = 75;
  148. const aspect = 2; // valeur par défaut du canevas
  149. const near = 0.1;
  150. const far = 5;
  151. const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  152. </pre>
  153. <p><code class="notranslate" translate="no">fov</code> est le raccourci pour <code class="notranslate" translate="no">field of view</code> ou champ de vision.
  154. Dans ce cas, 75 degrés d'ouverture verticale. Il est à noter que
  155. la plupart des angles dans Three.js sont exprimés en radians à l'exception
  156. de la caméra perspective.</p>
  157. <p><code class="notranslate" translate="no">aspect</code> est le ratio d'affichage dans le canevas. Cela sera détaillé
  158. <a href="responsive.html">dans un autre article</a>. Toutefois, par défaut,
  159. un canevas est de taille 300x150 pixels ce qui lui confère un ratio de 300/150 ou 2.</p>
  160. <p><code class="notranslate" translate="no">near</code> et <code class="notranslate" translate="no">far</code> délimitent la portion de l'espace devant la caméra dont
  161. le rendu est effectué. Tout ce qui est avant ou après est découpé (<em>clipped</em>),
  162. donc non dessiné.</p>
  163. <p>Ces 4 paramètres définissent une pyramide tronquée ou <em>"frustum"</em>.
  164. En d'autres termes, il s'agit d'une autre forme 3D à l'instar des sphères,
  165. cubes et prismes.</p>
  166. <p><img src="../resources/frustum-3d.svg" width="500" class="threejs_center"></p>
  167. <p>La hauteur des plans <em>near</em> et <em>far</em> est déterminée
  168. par le champ de vision. La largeur de ces plans est déterminée par le champ de vision et le ratio.</p>
  169. <p>Tout ce qui est dans le <em>frustum</em> est dessiné. Ce qui est à l'extérieur ne l'est pas.</p>
  170. <p>La caméra regarde par défaut suivant l'axe -Z, +Y pointant le haut.
  171. Nous mettons notre cube à l'origine donc nous devons déplacer la caméra de l'origine légèrement vers son arrière
  172. pour voir quelque chose.</p>
  173. <pre class="prettyprint showlinemods notranslate lang-js" translate="no">camera.position.z = 2;
  174. </pre>
  175. <p>Voici ce que nous voudrions voir :</p>
  176. <p><img src="../resources/scene-down.svg" width="500" class="threejs_center"></p>
  177. <p>Dans le schéma ci-dessus, nous pouvons voir que notre caméra est placée
  178. en <code class="notranslate" translate="no">z = 2</code>. Elle regarde le long de la direction -Z.
  179. Notre <em>frustum</em> démarre à 0.1 unités de la caméra et s'étend jusqu'à 5 unités devant elle.
  180. Comme le schéma est vu du haut, le champ de vision est affecté par le ratio du canvas.
  181. Celui-ci est deux fois plus large que haut donc le champ de vision horizontal
  182. est plus grand que les 75 degrés spécifiés pour le champ de vision vertical.</p>
  183. <p>Ensuite, nous créons une <a href="/docs/#api/en/scenes/Scene"><code class="notranslate" translate="no">Scene</code></a>. Dans Three.js, une <a href="/docs/#api/en/scenes/Scene"><code class="notranslate" translate="no">Scene</code></a> est la racine
  184. du graphe de scène. Tout ce que nous voulons que Three.js dessine doit être ajouté
  185. à la scène. Cela sera davantage détaillé dans <a href="scenegraph.html">un futur article sur le fonctionnement des scènes</a>.</p>
  186. <pre class="prettyprint showlinemods notranslate lang-js" translate="no">const scene = new THREE.Scene();
  187. </pre>
  188. <p>Ensuite nous créons une géométrie de type <a href="/docs/#api/en/geometries/BoxGeometry"><code class="notranslate" translate="no">BoxGeometry</code></a> qui contient les données pour un parallélépipède.
  189. Quasiment tout ce que nous souhaitons afficher avec Three.js nécessite une
  190. géométrie qui définit les sommets qui composent nos objets 3D.</p>
  191. <pre class="prettyprint showlinemods notranslate lang-js" translate="no">const boxWidth = 1;
  192. const boxHeight = 1;
  193. const boxDepth = 1;
  194. const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
  195. </pre>
  196. <p>Puis nous créons un matériau basique et fixons sa couleur, qui peut être spécifiée au format hexadécimal (6 chiffres) du standard CSS.</p>
  197. <pre class="prettyprint showlinemods notranslate lang-js" translate="no">const material = new THREE.MeshBasicMaterial({color: 0x44aa88});
  198. </pre>
  199. <p>Nous créons ensuite un maillage (<a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a>). Dans Three.js, il représente la combinaison
  200. d'une <code class="notranslate" translate="no">Geometry</code> (forme de l'objet) et d'un matériau (<a href="/docs/#api/en/materials/Material"><code class="notranslate" translate="no">Material</code></a> - aspect
  201. d'un objet, brillant ou plat, quelle couleur, quelle texture appliquer, etc.)
  202. ainsi que la position, l'orientation et l'échelle de l'objet dans la scène.</p>
  203. <pre class="prettyprint showlinemods notranslate lang-js" translate="no">const cube = new THREE.Mesh(geometry, material);
  204. </pre>
  205. <p>Finalement, nous ajoutons le maillage à la scène.</p>
  206. <pre class="prettyprint showlinemods notranslate lang-js" translate="no">scene.add(cube);
  207. </pre>
  208. <p>Nous pouvons, maintenant, effectuer le rendu de la scène en appelant la fonction <em>render</em> du <em>renderer</em>
  209. et en lui passant la scène et la caméra.</p>
  210. <pre class="prettyprint showlinemods notranslate lang-js" translate="no">renderer.render(scene, camera);
  211. </pre>
  212. <p>Voici un exemple fonctionnel :</p>
  213. <p></p><div translate="no" class="threejs_example_container notranslate">
  214. <div><iframe class="threejs_example notranslate" translate="no" style=" " src="/manual/examples/resources/editor.html?url=/manual/examples/fundamentals.html"></iframe></div>
  215. <a class="threejs_center" href="/manual/examples/fundamentals.html" target="_blank">Cliquer ici pour ouvrir dans une fenêtre séparée</a>
  216. </div>
  217. <p></p>
  218. <p>Il est difficile de déterminer s'il s'agit d'un cube 3D puisque nous
  219. l'observons suivant l'axe -Z sur lequel le cube est lui même aligné.
  220. Nous n'en voyons donc qu'une face.</p>
  221. <p>Animons notre cube en le faisant tourner et cela fera clairement
  222. apparaître qu'il est dessiné en 3D. Pour l'animation, nous effectuerons son rendu
  223. dans une boucle de rendu en utilisant
  224. <a href="https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame"><code class="notranslate" translate="no">requestAnimationFrame</code></a>.</p>
  225. <p>Voici notre boucle :</p>
  226. <pre class="prettyprint showlinemods notranslate lang-js" translate="no">function render(time) {
  227. time *= 0.001; // convertis le temps en secondes
  228. cube.rotation.x = time;
  229. cube.rotation.y = time;
  230. renderer.render(scene, camera);
  231. requestAnimationFrame(render);
  232. }
  233. requestAnimationFrame(render);
  234. </pre>
  235. <p><code class="notranslate" translate="no">requestAnimationFrame</code> est une requête auprès du navigateur dans le cas où vous
  236. voulez animer quelque chose. Nous lui passons une fonction à appeler.
  237. Dans notre cas, c'est la fonction <code class="notranslate" translate="no">render</code>. Le navigateur appellera cette fonction
  238. et, si nous mettons à jour l'affichage de la page, le navigateur refera le rendu
  239. de la page. Dans notre cas, nous appelons la fonction <code class="notranslate" translate="no">renderer.render</code> de Three.js
  240. qui dessinera notre scène.</p>
  241. <p><code class="notranslate" translate="no">requestAnimationFrame</code> passe à notre fonction le temps depuis lequel la page est chargée.
  242. Il est mesuré en millisecondes. Il est parfois plus facile de travailler
  243. avec des secondes. C'est pourquoi, nous l'avons converti.</p>
  244. <p>A présent, nous appliquons sur le cube des rotations le long des axes X et Y en fonction du temps écoulé.
  245. Les angles de rotation sont exprimés en <a href="https://en.wikipedia.org/wiki/Radian">radians</a>.
  246. Sachant que 2 PI radians fait faire un tour complet, notre cube effectuera une rotation complète
  247. sur chaque axe en, à peu près, 6,28 secondes.</p>
  248. <p>Nous effectuons alors le rendu de la scène et
  249. demandons une autre image pour l'animation afin de poursuivre notre boucle.</p>
  250. <p>A l'extérieur de la boucle, nous appelons <code class="notranslate" translate="no">requestAnimationFrame</code> une première fois pour activer la boucle.</p>
  251. <p></p><div translate="no" class="threejs_example_container notranslate">
  252. <div><iframe class="threejs_example notranslate" translate="no" style=" " src="/manual/examples/resources/editor.html?url=/manual/examples/fundamentals-with-animation.html"></iframe></div>
  253. <a class="threejs_center" href="/manual/examples/fundamentals-with-animation.html" target="_blank">Cliquer ici pour ouvrir dans une fenêtre séparée</a>
  254. </div>
  255. <p></p>
  256. <p>C'est un peu mieux mais il est toujours difficile de percevoir la 3D.
  257. Ce qui aiderait serait d'ajouter de la lumière.
  258. Three.js propose plusieurs type de lumière que nous détaillerons dans
  259. <a href="lights.html">un futur article</a>. Pour le moment, créons une lumière directionnelle.</p>
  260. <pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
  261. const color = 0xFFFFFF;
  262. const intensity = 3;
  263. const light = new THREE.DirectionalLight(color, intensity);
  264. light.position.set(-1, 2, 4);
  265. scene.add(light);
  266. }
  267. </pre>
  268. <p>Les lumières directionnelles ont une position et une cible. Les deux sont par défaut en 0, 0, 0.
  269. Dans notre cas, nous positionnons la lumière en -1, 2, 4, de manière à ce qu'elle soit légèrement
  270. sur la gauche, au dessus et derrière notre caméra. La cible est toujours 0, 0, 0 donc elle va
  271. éclairer vers l'origine.</p>
  272. <p>Nous avons également besoin de changer le matériau car <a href="/docs/#api/en/materials/MeshBasicMaterial"><code class="notranslate" translate="no">MeshBasicMaterial</code></a> ne s'applique pas aux
  273. lumières. Nous le remplaçons par un <a href="/docs/#api/en/materials/MeshPhongMaterial"><code class="notranslate" translate="no">MeshPhongMaterial</code></a> qui est affecté par les sources lumineuses.</p>
  274. <pre class="prettyprint showlinemods notranslate lang-js" translate="no">-const material = new THREE.MeshBasicMaterial({color: 0x44aa88}); // cyan
  275. +const material = new THREE.MeshPhongMaterial({color: 0x44aa88}); // cyan
  276. </pre>
  277. <p>Voici à présent la nouvelle structure de notre programme :</p>
  278. <div class="threejs_center"><img src="../resources/images/threejs-1cube-with-directionallight.svg" style="width: 500px;"></div>
  279. <p>Et voici son fonctionnement :</p>
  280. <p></p><div translate="no" class="threejs_example_container notranslate">
  281. <div><iframe class="threejs_example notranslate" translate="no" style=" " src="/manual/examples/resources/editor.html?url=/manual/examples/fundamentals-with-light.html"></iframe></div>
  282. <a class="threejs_center" href="/manual/examples/fundamentals-with-light.html" target="_blank">Cliquer ici pour ouvrir dans une fenêtre séparée</a>
  283. </div>
  284. <p></p>
  285. <p>Cela devrait à présent apparaître très clairement en 3D.</p>
  286. <p>Pour le sport, ajoutons 2 cubes supplémentaires.</p>
  287. <p>Nous partageons la même géométrie pour chaque cube mais un matériau différent par cube
  288. afin qu'ils aient une couleur différente.</p>
  289. <p>Tout d'abord, nous définissons une fonction qui crée un nouveau matériau
  290. avec la couleur spécifiée. Ensuite, elle créé un maillage à partir de la
  291. géométrie spécifiée, l'ajoute à la scène et change sa position en X.</p>
  292. <pre class="prettyprint showlinemods notranslate lang-js" translate="no">function makeInstance(geometry, color, x) {
  293. const material = new THREE.MeshPhongMaterial({color});
  294. const cube = new THREE.Mesh(geometry, material);
  295. scene.add(cube);
  296. cube.position.x = x;
  297. return cube;
  298. }
  299. </pre>
  300. <p>Ensuite, nous l'appellons à 3 reprises avec 3 différentes couleurs
  301. et positions en X, puis nous conservons ces instances de <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> dans un tableau.</p>
  302. <pre class="prettyprint showlinemods notranslate lang-js" translate="no">const cubes = [
  303. makeInstance(geometry, 0x44aa88, 0),
  304. makeInstance(geometry, 0x8844aa, -2),
  305. makeInstance(geometry, 0xaa8844, 2),
  306. ];
  307. </pre>
  308. <p>Enfin, nous faisons tourner ces 3 cubes dans notre fonction de rendu.
  309. Nous calculons une rotation légèrement différente pour chacun d'eux.</p>
  310. <pre class="prettyprint showlinemods notranslate lang-js" translate="no">function render(time) {
  311. time *= 0.001; // conversion du temps en secondes
  312. cubes.forEach((cube, ndx) =&gt; {
  313. const speed = 1 + ndx * .1;
  314. const rot = time * speed;
  315. cube.rotation.x = rot;
  316. cube.rotation.y = rot;
  317. });
  318. ...
  319. </pre>
  320. <p>et voilà le résultat.</p>
  321. <p></p><div translate="no" class="threejs_example_container notranslate">
  322. <div><iframe class="threejs_example notranslate" translate="no" style=" " src="/manual/examples/resources/editor.html?url=/manual/examples/fundamentals-3-cubes.html"></iframe></div>
  323. <a class="threejs_center" href="/manual/examples/fundamentals-3-cubes.html" target="_blank">Cliquer ici pour ouvrir dans une fenêtre séparée</a>
  324. </div>
  325. <p></p>
  326. <p>Si nous le comparons au schéma précédent, nous constatons qu'il
  327. est conforme à nos attentes. Les cubes en X = -2 et X = +2
  328. sont partiellement en dehors du <em>frustum</em>. Ils sont, de plus,
  329. exagérément déformés puisque le champ de vision dépeint au travers du
  330. canevas est extrême.</p>
  331. <p>A présent, notre programme est schématisé par la figure suivante :</p>
  332. <div class="threejs_center"><img src="../resources/images/threejs-3cubes-scene.svg" style="width: 610px;"></div>
  333. <p>Comme nous pouvons le constater, nous avons 3 objets de type <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a>, chacun référençant
  334. la même <a href="/docs/#api/en/geometries/BoxGeometry"><code class="notranslate" translate="no">BoxGeometry</code></a>. Chaque <a href="/docs/#api/en/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> référence également un <a href="/docs/#api/en/materials/MeshPhongMaterial"><code class="notranslate" translate="no">MeshPhongMaterial</code></a> unique
  335. de sorte que chaque cube possède une couleur différente.</p>
  336. <p>Nous espérons que cette courte introduction vous aide à débuter.
  337. <a href="responsive.html">La prochaine étape consiste à rendre notre code réactif et donc adaptable à de multiples situations</a>.</p>
  338. <div class="threejs_bottombar">
  339. <h3>es6 modules, Three.js et structure de dossiers</h3>
  340. <p>Depuis la version 106 (r106), l'utilisation de Three.js privilégie les <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import">modules es6</a>.</p>
  341. <p>
  342. Ils sont chargés via le mot-clé <code class="notranslate" translate="no">import</code> dans un script ou en ligne
  343. par le biais d'une balise <code class="notranslate" translate="no">&lt;script type="module"&gt;</code>. Voici un exemple d'utilisation avec les deux :
  344. </p>
  345. <pre class="prettyprint">&lt;script type="module"&gt;
  346. import * as THREE from 'three';
  347. ...
  348. &lt;/script&gt;
  349. </pre>
  350. <p>
  351. Les chemins doivent être absolus ou relatifs. Un chemin relatif commencent toujours par
  352. <code class="notranslate" translate="no">./</code> ou par <code class="notranslate" translate="no">../</code>,
  353. ce qui est différent des autres balises telles que <code class="notranslate" translate="no">&lt;img&gt;</code> et <code class="notranslate" translate="no">&lt;a&gt;</code>.
  354. </p>
  355. <p>
  356. Les références à un même script ne seront chargées qu'une seule fois à partir du
  357. moment où leur chemin absolu est exactement identique. Pour Three.js, cela veut
  358. dire qu'il est nécessaire de mettre toutes les bibliothèques d'exemples dans une
  359. structure correcte pour les dossiers :
  360. </p>
  361. <pre class="dos">unDossier
  362. |
  363. ├-build
  364. | |
  365. | +-three.module.js
  366. |
  367. +-examples
  368. |
  369. +-jsm
  370. |
  371. +-controls
  372. | |
  373. | +-OrbitControls.js
  374. | +-TrackballControls.js
  375. | +-...
  376. |
  377. +-loaders
  378. | |
  379. | +-GLTFLoader.js
  380. | +-...
  381. |
  382. ...
  383. </pre>
  384. <p>
  385. La raison nécessitant cette structuration des dossiers est parce que les scripts
  386. des exemples tels que <a href="https://github.com/mrdoob/three.js/blob/master/examples/jsm/controls/OrbitControls.js"><code class="notranslate" translate="no">OrbitControls.js</code></a>
  387. ont des chemins relatifs tels que :
  388. </p>
  389. <pre class="prettyprint">import * as THREE from '../../../build/three.module.js';
  390. </pre>
  391. <p>
  392. Utiliser la même structure permet de s'assurer, lors de l'importation de
  393. Three.js et d'une autre bibliothèque d'exemple, qu'ils référenceront le même fichier
  394. three.module.js.
  395. </p>
  396. <pre class="prettyprint">import * as THREE from './someFolder/build/three.module.js';
  397. import {OrbitControls} from './someFolder/addons/controls/OrbitControls.js';
  398. </pre>
  399. <p>Cela est valable aussi lors de l'utilisation d'un CDN. Assurez vous que vos chemins versThis includes when using a CDN. Be <code class="notranslate" translate="no">three.modules.js</code> terminent par
  400. <code class="notranslate" translate="no">/build/three.modules.js</code>. Par exemple :</p>
  401. <pre class="prettyprint">import * as THREE from 'https://cdn.jsdelivr.net/npm/three@&lt;version&gt;/<b>build/three.module.js</b>';
  402. import {OrbitControls} from 'https://cdn.jsdelivr.net/npm/three@&lt;version&gt;/addons/controls/OrbitControls.js';
  403. </pre>
  404. </div>
  405. </div>
  406. </div>
  407. </div>
  408. <script src="../resources/prettify.js"></script>
  409. <script src="../resources/lesson.js"></script>
  410. </body></html>