{"id":733,"date":"2013-10-11T09:15:07","date_gmt":"2013-10-11T08:15:07","guid":{"rendered":"http:\/\/coralia-wsd.com\/site\/?p=733"},"modified":"2013-10-11T09:15:07","modified_gmt":"2013-10-11T08:15:07","slug":"canvas-3d-webgl-plus-facile-avec-three-js","status":"publish","type":"post","link":"http:\/\/www.coralia-wsd.com\/site\/canvas-3d-webgl-plus-facile-avec-three-js\/","title":{"rendered":"Canvas 3D (WebGL) plus facile avec Three.js"},"content":{"rendered":"<div class=\"l-submain\"><div class=\"l-submain-h g-html i-cf\"><p>Nous avons tous d\u00e9j\u00e0 vu des sites de grandes marques nous en mettant plein la vue avec des animations 3D interactives, ou des d\u00e9monstrations technologiques qui font r\u00eaver. On pense ici \u00e0 quelques berlines allemandes parfaitement mod\u00e9lis\u00e9es qu\u2019il est possible d\u2019inspecter sous tous ses angles avec un simple mouvement de la souris&#8230; Bien souvent d\u00e9velopp\u00e9es en Flash avec la librairie\u00a0<a href=\"https:\/\/code.google.com\/p\/papervision3d\/\">Papervision3D<\/a>\u00a0ces\u00a0animations en jettent un max, mais restent d\u00e9pendantes du plug-in d&rsquo;Adobe qui est de moins en moins populaire et \u00ab\u00a0incompatible\u00a0\u00bb tablette et smartphone.<\/p>\n<p>Aujourd\u2019hui la tendance est au HTML5 et CSS3, parsem\u00e9 d\u2019un peu de JavaScript. \u00d4 chance, le W3C et ses contributeurs ont justement pr\u00e9vu de passer par\u00a0<a href=\"http:\/\/www.alsacreations.com\/tuto\/lire\/1484-introduction.html\">Canvas<\/a>\u00a0(qui permet d\u00e9j\u00e0 de dessiner dans une page web en 2D) pour exploiter une sc\u00e8ne 3D avec les standards du web.<\/p>\n<h3>Comment et pour qui ?<\/h3>\n<p>Pour ceux qui ne le savent pas, il existe deux composants HTML5 pour dessiner :<\/p>\n<ul>\n<li><strong>Canvas<\/strong>, qui permet de faire du dessin bitmap (en pixel)<\/li>\n<li><strong>SVG<\/strong>\u00a0pour le dessin vectoriel, souvent utilis\u00e9 en cartographie (\u00e0 l&rsquo;exception de Google Maps ou OpenStreetMap qui utilisent des mosa\u00efques d&rsquo;images)<\/li>\n<\/ul>\n<p>Je ne m\u2019attarderai pas sur ces composants, le web regorge de sujets qui en parlent d\u00e9j\u00e0 tr\u00e8s bien.<\/p>\n<p><img src=\"http:\/\/www.alsacreations.com\/xmedia\/doc\/full\/webgl.gif\" alt=\"WebGL\" \/><\/p>\n<p>Il existe en r\u00e9alit\u00e9 un troisi\u00e8me composant qui est lui d\u00e9di\u00e9 \u00e0 la 3D, il s\u2019agit de\u00a0<strong><a href=\"https:\/\/www.khronos.org\/registry\/webgl\/specs\/1.0\/\">WebGL<\/a><\/strong>\u00a0qui se base sur le standard 3D OpenGL. Il permet d\u2019exploiter les pilotes de la carte graphique et de tirer ainsi profit de l\u2019acc\u00e9l\u00e9ration mat\u00e9rielle, un atout majeur pour des rendus performants de formes et\/ou de textures complexes. En gros WebGL permet de g\u00e9n\u00e9rer un rendu 3D calcul\u00e9 par la carte graphique dans votre navigateur. Sous entendu : cette feignasse de carte graphique qui ne sert pas \u00e0 grand chose pour le rendu d\u2019une page Web va enfin se rendre utile.<\/p>\n<p>Seulement ce qu\u2019il faut savoir, c\u2019est que comme avec beaucoup des nouveaut\u00e9s apport\u00e9es par HTML5, il y a encore des restrictions li\u00e9es \u00e0 l\u2019impl\u00e9mentation de ces standards par les navigateurs.<\/p>\n<p>Ainsi je vais peut-\u00eatre refroidir les ardeurs de certains; WebGL est support\u00e9 par :<\/p>\n<ul>\n<li>Firefox \u00e0 partir de la version 4 ;<\/li>\n<li>Chrome \u00e0 partir de la version 9 ;<\/li>\n<li>Safari seulement si activ\u00e9 depuis le menu d\u00e9veloppement ;<\/li>\n<li>Internet Explorer \u00e0 partir de la version 11 seulement<\/li>\n<\/ul>\n<p>Les mobiles, souvent soumis \u00e0 plus de contraintes d&rsquo;\u00e9conomie d&rsquo;\u00e9nergie reconnaissent pour la plupart d\u00e9j\u00e0 ces instructions via les moteurs embarqu\u00e9s mais elles sont d\u00e9sactiv\u00e9es par d\u00e9faut. Et comme ce n\u2019est pas pas tr\u00e8s encourageant, mais qu&rsquo;il y a du mieux depuis que Microsoft s&rsquo;y est mis, il faut ajouter \u00e0 cela que certaines cartes graphiques ne supportent pas WebGL. C\u2019est notamment le cas sur certains mod\u00e8les de Mac. Voir\u00a0<a href=\"http:\/\/www.khronos.org\/webgl\/wiki\/BlacklistsAndWhitelists\">BlacklistsAndWhitelists WebGL (informations de support plus d\u00e9taill\u00e9es).<\/a><\/p>\n<p>Bon bon bon&#8230; alors pourquoi je vous parle de \u00e7a si visiblement on ne peux pas encore l\u2019utiliser en production \u00e0 l\u2019heure actuelle ? Et bien d\u00e9j\u00e0 parce que comme beaucoup de choses apport\u00e9es par HTML5 c\u2019est fun et dans un avenir proche \u00e7a deviendra viable en production. Et parce que \u00e7a ne fait pas de mal de se faire un peu plaisir avec les nouvelles techno sur des projets innovants. Parce que l\u2019innovation c\u2019est le progr\u00e8s et que c\u2019est bon pour l\u2019\u00e9conomie !<\/p>\n<p>Et la petite surprise du chef c\u2019est qu\u2019on peut quand m\u00eame faire un peu de 3D sans WebGL ! Et oui, car la 3D finalement \u00e7a reste du dessin 2D auquel on ajoute une perspective (comment \u00e7a je simplifie un peu trop ?). De fait, on peut utiliser Canvas et SVG pour dessiner en 3D.<\/p>\n<p>Alors je vous rassure, il n\u2019est pas question de s\u2019amuser \u00e0 faire des calculs savants \u00e0 bases de matrices ou autres calculs trigonom\u00e9triques, il y a des gens tr\u00e8s cal\u00e9s en la mati\u00e8res qui nous ont m\u00e2ch\u00e9 le travail en amont et c\u2019est l\u00e0 que je vais vous parler de la librairie Three.js.<\/p>\n<p><img src=\"http:\/\/www.alsacreations.com\/xmedia\/doc\/full\/threejs.jpg\" alt=\"Three.js\" \/><\/p>\n<h3>La librairie Three.js<\/h3>\n<p><a href=\"http:\/\/threejs.org\/\"><strong>Three.js<\/strong><\/a>\u00a0c\u2019est donc une biblioth\u00e8que JavaScript qui va nous permettre de faire de la 3D \u00e0 la m\u00eame mani\u00e8re que Papervision3D le permettait en ActionScript dans Flash, mais cette fois-ci en ayant recours \u00e0 la technologie de notre choix pour le rendu. Le m\u00eame code \u00e9crit avec Three.js pourra donc \u00eatre utilis\u00e9 avec Canvas (2D) ou WebGL.<\/p>\n<p>Attention cependant, WebGL utilise l\u2019acc\u00e9l\u00e9ration mat\u00e9rielle de la carte graphique, bien plus habile avec les calculs matriciels, ce dont Canvas est incapable. Il y a donc de grosses diff\u00e9rences de performances entre l\u2019utilisation des deux technologies. Canvas ne pourra donc \u00eatre utilis\u00e9 que pour des rendus relativement simples si l\u2019on ne veut pas voir le navigateur flancher sous la masse de calculs.<\/p>\n<p>Commen\u00e7ons par t\u00e9l\u00e9charger la librairie \u00e0 l\u2019adresse suivante sur le d\u00e9p\u00f4t Github :<a href=\"https:\/\/github.com\/mrdoob\/three.js\/\">https:\/\/github.com\/mrdoob\/three.js\/<\/a>\u00a0(cliquez sur\u00a0<em>Download ZIP<\/em>).<\/p>\n<p>Puis initialisons une page HTML comme vous en avez l\u2019habitude. Dans cette page nous allons inclure la librairie Three.js et ajouter un conteneur dans le body. Et juste avant de fermer le body on ajoute un balise script dans laquelle nous ins\u00e9rerons le code JavaScript pour initialiser notre sc\u00e8ne en 3D.<\/p>\n<pre><code>&lt;!doctype html&gt; &lt;html&gt; &lt;head&gt; &lt;title&gt;Mon premier rendu 3D avec Three.js&lt;\/title&gt; &lt;meta charset=\"utf-8\"&gt; &lt;link href=\"css\/main.css\" rel=\"stylesheet\"\/&gt; &lt;\/head&gt; &lt;body&gt; &lt;div id=\"container\"&gt;&lt;\/div&gt; &lt;script src=\"http:\/\/mrdoob.github.com\/three.js\/build\/three.min.js\"&gt;&lt;\/script&gt; &lt;script type=\"text\/javascript\"&gt; &lt;!-- C'est ici que nous utiliserons Three.js --&gt; &lt;\/script&gt; &lt;\/body&gt; &lt;\/html&gt;<\/code><\/pre>\n<p>Nous allons donc initialiser notre sc\u00e8ne avec le code suivant :<\/p>\n<pre><code>var renderer, scene, camera, mesh; init(); function init(){ \/\/ on initialise le moteur de rendu renderer = new THREE.WebGLRenderer(); \/\/ si WebGL ne fonctionne pas sur votre navigateur vous pouvez utiliser le moteur de rendu Canvas \u00e0 la place \/\/ renderer = new THREE.CanvasRenderer(); renderer.setSize( window.innerWidth, window.innerHeight ); document.getElementById('container').appendChild(renderer.domElement); \/\/ on initialise la sc\u00e8ne scene = new THREE.Scene(); \/\/ on initialise la camera que l\u2019on place ensuite sur la sc\u00e8ne camera = new THREE.PerspectiveCamera(50, window.innerWidth \/ window.innerHeight, 1, 10000 ); camera.position.set(0, 0, 1000); scene.add(camera); \/\/ on cr\u00e9\u00e9 un cube au quel on d\u00e9finie un mat\u00e9riau puis on l\u2019ajoute \u00e0 la sc\u00e8ne var geometry = new THREE.CubeGeometry( 200, 200, 200 ); var material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } ); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); \/\/ on effectue le rendu de la sc\u00e8ne renderer.render( scene, camera ); }<\/code><\/pre>\n<p>Ces fonctions ne viennent pas du n\u00e9ant, vous pouvez les retrouver dans la<a href=\"http:\/\/threejs.org\/docs\/\">documentation Three.js<\/a>.<\/p>\n<p>Et l\u00e0, oh magie, vous devriez voir&#8230; un cube rouge s\u2019afficher.<\/p>\n<p><a href=\"http:\/\/www.alsacreations.com\/xmedia\/tuto\/webgl\/index.html\">D\u00e9monstration<\/a><\/p>\n<p>\u201cTout \u00e7a pour \u00e7a\u201d me direz-vous ? Oui, mais ce carr\u00e9 est en 3D. Si, si je vous l\u2019assure, et je vais m\u00eame vous le prouver ! Pour s&rsquo;en rendre compte, rien de mieux que de le faire tourner sur lui m\u00eame. On commence par ajouter une fonction<code>animate()<\/code>\u00a0qui sera appel\u00e9e r\u00e9cursivement pour mettre \u00e0 jours les attributs de l&rsquo;objet \u00e0 animer.<\/p>\n<pre><code>function animate(){ requestAnimationFrame( animate ); mesh.rotation.x += 0.01; mesh.rotation.y += 0.02; renderer.render( scene, camera ); }<\/code><\/pre>\n<p>On ajoute un appel \u00e0 cette fonction juste apr\u00e8s l\u2019appel \u00e0 la fonction\u00a0<code>init()<\/code>pr\u00e9c\u00e9dente, puis nous pouvons maintenant retirer la fonction de rendu dans la fonction\u00a0<code>init()<\/code>\u00a0puisque l\u2019appel se fait maintenant via la fonction\u00a0<code>animate()<\/code>. Voil\u00e0 le code final :<\/p>\n<pre><code>var renderer, scene, camera, mesh; init(); animate(); function init(){ \/\/ on initialise le moteur de rendu renderer = new THREE.WebGLRenderer(); \/\/ si WebGL ne fonctionne pas sur votre navigateur vous pouvez utiliser le moteur de rendu Canvas \u00e0 la place \/\/ renderer = new THREE.CanvasRenderer(); renderer.setSize( window.innerWidth, window.innerHeight ); document.getElementById('container').appendChild(renderer.domElement); \/\/ on initialise la sc\u00e8ne scene = new THREE.Scene(); \/\/ on initialise la camera que l\u2019on place ensuite sur la sc\u00e8ne camera = new THREE.PerspectiveCamera(50, window.innerWidth \/ window.innerHeight, 1, 10000 ); camera.position.set(0, 0, 1000); scene.add(camera); \/\/ on cr\u00e9\u00e9 un cube au quel on d\u00e9finie un mat\u00e9riau puis on l\u2019ajoute \u00e0 la sc\u00e8ne var geometry = new THREE.CubeGeometry( 200, 200, 200 ); var material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } ); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } function animate(){ \/\/ on appel la fonction animate() r\u00e9cursivement \u00e0 chaque frame requestAnimationFrame( animate ); \/\/ on fait tourner le cube sur ses axes x et y mesh.rotation.x += 0.01; mesh.rotation.y += 0.02; \/\/ on effectue le rendu de la sc\u00e8ne renderer.render( scene, camera ); }<\/code><\/pre>\n<p>Actualisez la page et vous devriez maintenant voir le cube tourner sur lui m\u00eame. F\u00e9licitations, vous savez maintenant faire une animation en\u00a0<strong>v\u00e9ritable 3D<\/strong>\u00a0dans votre navigateur !<\/p>\n<p><a href=\"http:\/\/www.alsacreations.com\/xmedia\/tuto\/webgl\/index2.html\">D\u00e9monstration<\/a><\/p>\n<h3>Textures et \u00e9clairage<\/h3>\n<p>Une derni\u00e8re petite \u00e9tape va consister remplacer notre cube par une sph\u00e8re et \u00e0 lui appliquer une texture (image JPEG) que nous allons \u00e9clairer avec une lumi\u00e8re directionnelle pour donner un peu de cachet \u00e0 tout \u00e7a.<\/p>\n<p>On va donc remplacer la partie concernant la cr\u00e9ation du cube par le code suivant :<\/p>\n<pre><code>\/\/ on cr\u00e9\u00e9 la sph\u00e8re et on lui applique une texture sous forme d\u2019image var geometry = new THREE.SphereGeometry( 200, 32, 32 ); var material = new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture('metal.jpg', new THREE.SphericalReflectionMapping()), overdraw: true } ); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); \/\/ on ajoute une lumi\u00e8re blanche var lumiere = new THREE.DirectionalLight( 0xffffff, 1.0 ); lumiere.position.set( 0, 0, 400 ); scene.add( lumiere );<\/code><\/pre>\n<p>Et voil\u00e0 ! Vous avez une sph\u00e8re m\u00e9tallique qui tourne sur elle m\u00eame avec un beau reflet lumineux. Consultez le code source de la d\u00e9monstration pour bien visualiser les diff\u00e9rentes parties entrant en jeu.<\/p>\n<p><a href=\"http:\/\/www.alsacreations.com\/xmedia\/tuto\/webgl\/index3.html\">D\u00e9monstration<\/a><\/p>\n<p>Attention,\u00a0d\u00e9sormais pour des contraintes de s\u00e9curit\u00e9, certaines op\u00e9rations 3D et notamment le chargement d&rsquo;images de textures imposent de consulter les pages en mode http:\/\/ et non pas en local sur votre disque (file:\/\/). Consultez la\u00a0<a href=\"http:\/\/www.alsacreations.com\/astuce\/lire\/1436-console-javascript.html\">console JavaScript<\/a>\u00a0pour v\u00e9rifier s&rsquo;il y a des bugs.<\/p>\n<h3>Conclusion<\/h3>\n<p>On va s\u2019arr\u00eater l\u00e0 pour le moment. Sachez simplement que la librairie permet beaucoup de libert\u00e9s. Vous pouvez par exemple :<\/p>\n<ul>\n<li>charger des objets 3D mod\u00e9lis\u00e9s avec votre logiciel de mod\u00e9lisation 3D pr\u00e9f\u00e9r\u00e9 (3DS Max, Maya,\u00a0<a href=\"http:\/\/www.blender.org\/\">Blender<\/a>&#8230;) et export\u00e9s au format\u00a0<a href=\"http:\/\/www.khronos.org\/collada\/\">Collada<\/a>\u00a0pour les importer dans votre sc\u00e8ne et les animer ensuite.<\/li>\n<li>brancher des \u00e9v\u00e9nements JavaScript clavier\/souris (onclick, onkeypress&#8230;) pour piloter la vue 3D<\/li>\n<li>exploiter l&rsquo;<a href=\"http:\/\/www.w3.org\/TR\/gamepad\/\">API Gamepad<\/a>\u00a0pour contr\u00f4ler vos jeux avec une manette de jeu, ou bien encore\u00a0<a href=\"http:\/\/www.w3.org\/TR\/pointerlock\/\">Pointer Lock<\/a>\u00a0pour la souris.<\/li>\n<\/ul>\n<p>Techniquement il est tout \u00e0 fait possible de faire un jeux vid\u00e9o 3D complet comme Doom ou\u00a0<a href=\"http:\/\/code.google.com\/p\/quake2-gwt-port\/\">Quake 2<\/a>.<\/p>\n<div><iframe loading=\"lazy\" src=\"http:\/\/www.youtube-nocookie.com\/embed\/fyfu4OwjUEI?rel=0\" frameborder=\"0\" width=\"540\" height=\"304\"><\/iframe><\/div>\n<p>On peut d&rsquo;ailleurs citer l&rsquo;excellent travail de\u00a0<a href=\"http:\/\/bkcore.com\/\">Thibaut Despoulain<\/a>\u00a0qui a r\u00e9alis\u00e9 un superbe jeu de course du nom de\u00a0<a href=\"http:\/\/hexgl.bkcore.com\/\">HexGL<\/a>\u00a0avec Three.js et HTML5.<\/p>\n<p><img src=\"http:\/\/www.alsacreations.com\/xmedia\/doc\/full\/hexgl.jpg\" alt=\"HexGL\" \/><\/p>\n<p>Soyons fous, il serait envisageable de\u00a0<em>texturiser<\/em>\u00a0un objet 3D avec un vid\u00e9o via l\u2019API Video de HTML5 qui pourrait elle m\u00eame se baser sur l\u2019API WebRTC et la m\u00e9thode<code>getUserMedia()<\/code>\u00a0pour capturer la webcam de l\u2019utilisateur (Quelle est l&rsquo;utilit\u00e9 de faire \u00e7a ? Je n&rsquo;en sais rien mais c&rsquo;est un bon exemple de la compl\u00e9mentarit\u00e9 des nouveaux composants de HTML5).<\/p>\n<\/div><\/div>","protected":false},"excerpt":{"rendered":"<p>Nous avons tous d\u00e9j\u00e0 vu des sites de grandes marques nous en mettant plein la vue avec des animations 3D interactives, ou des d\u00e9monstrations technologiques qui font r\u00eaver. On pense ici \u00e0 quelques berlines allemandes parfaitement mod\u00e9lis\u00e9es qu\u2019il est possible&#8230;<\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[17],"tags":[],"_links":{"self":[{"href":"http:\/\/www.coralia-wsd.com\/site\/wp-json\/wp\/v2\/posts\/733"}],"collection":[{"href":"http:\/\/www.coralia-wsd.com\/site\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.coralia-wsd.com\/site\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.coralia-wsd.com\/site\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"http:\/\/www.coralia-wsd.com\/site\/wp-json\/wp\/v2\/comments?post=733"}],"version-history":[{"count":2,"href":"http:\/\/www.coralia-wsd.com\/site\/wp-json\/wp\/v2\/posts\/733\/revisions"}],"predecessor-version":[{"id":3140,"href":"http:\/\/www.coralia-wsd.com\/site\/wp-json\/wp\/v2\/posts\/733\/revisions\/3140"}],"wp:attachment":[{"href":"http:\/\/www.coralia-wsd.com\/site\/wp-json\/wp\/v2\/media?parent=733"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.coralia-wsd.com\/site\/wp-json\/wp\/v2\/categories?post=733"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.coralia-wsd.com\/site\/wp-json\/wp\/v2\/tags?post=733"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}