Tuto en 30 minutes: Comment faire de la 3D dans un navigateur web.

Peut-être êtes vous déjà tombés sur un site internet qui vous a impressionné : complétement différent, immersif, en trois dimensions. Un truc qui change vraiment !

Si vous n’êtes pas branchés technique, vous vous êtes émerveillés et êtes passés à autre chose. En revanche, si vous aimez bien connaitre le fonctionnement de ce genre de site vous vous êtes interrogés : comment faire ?

Three.js : Une librairie JS pour la 3D

En réalité, ce type de site internet internet est bien souvent conçu grâce à la librairie Three.js qui, pour la petite histoire, permet de simplifier grandement le développement 3D et est basée sur le moteur WebGL.

Plutôt qu’un long discours, un petit tutoriel. Il va s’agir ici de représenter la terre, les nuages et son relief en 3D pour arriver à un résultat similaire à celui-ci dessous.

Vous êtes prêt ? C’est parti !

Etape 1 : Initialiser la scène Three.js

<html>

<head>

    <title>Tutoriel Terre three.js</title>

    <style>

        body { margin: 0; }

        canvas { width: 100%; height: 100% }

    </style>

</head>

<body>

<script src="js/three.js"></script>

<script src="js/OrbitControls.js"></script>

<script>

    //Initialisation//

    var scene = new THREE.Scene();

    var camera = new THREE.PerspectiveCamera( 45, window.innerWidth/window.innerHeight, 1, 1000 );

    var renderer = new THREE.WebGLRenderer();

    renderer.setSize( window.innerWidth, window.innerHeight );

    document.body.appendChild( renderer.domElement );

    camera.position.set(0,0,100);

Au début, vous reconnaitrez les balises html classiques, suivi d’un peu de style : on va juste dire que notre environnement 3D prendra l’ensemble de notre écran (100% en height et en width).

Ensuite, on charge Three.js ainsi qu’un script bien pratique qui va nous permettre de controler l’orbite de notre planète en se déplacant autour et en zoomant ou bien dézoomant à l’aide du scroll : OrbitControls.js

Puis on ouvre la balise <script> et on commence à entrer dans le vif du sujet.

var camera = new THREE.PerspectiveCamera( 45, window.innerWidth/window.innerHeight, 1, 1000 );

Cette ligne nous permet de définir une caméra. Premier élément de notre simulation 3D. Les paramètres de la fonction définissent dans l’ordre :

  • L’ouverture de l’angle
  • L’aspect du ratio
  • La valeur en dessous de laquelle les éléments ne seront pas traités
  • La valeur en dessus de laquelle les éléments ne seront pas traités
    var renderer = new THREE.WebGLRenderer();

    renderer.setSize( window.innerWidth, window.innerHeight );

    document.body.appendChild( renderer.domElement );

Les lignes ci-dessus définissent le moteur de rendu, sa taille ainsi que son positionnement dans le DOM (notre document html).

camera.position.set(0,0,100);

Enfin, on définit la position de notre caméra dans l’espace à l’aide de coordonnées X,Y,Z.

A ce stade, on a encore un écran noir, mais patience ! Passons maintenant au niveau supérieur.

Etape 2 : Un peu de lumière

A la suite du code ci-dessus, on définit la lumière qui va nous permettre de voir ce que l’on simule par la suite.

 //Création de la lumière

    //Ambiante

    var light = new THREE.AmbientLight( 0x888888 );

    scene.add( light );

    //Directionelle

    var light = new THREE.DirectionalLight( 0xfdfcf0, 1 );

    light.position.set(20,10,20);

    scene.add( light );

En réalité on va créer deux types de lumières que l’on va inscrire dans des variables pour plus de facilité.

Une lumière ambiante pour éclairer globalement notre scène et une lumière directionnelle pour lui donner un effet de « rayon solaire ». Le tout en n’oubliant pas d’ajouter notre variable à la scène grace au scene.add() ;

En réalité, chaque élément crée dans notre scène three.js devra respecter les deux étapes ci-dessus :

1° Création d’un élément et attribution des propriétés : par exemple la couleur hexadécimale ou le 0x remplace ici le ; ou bien la position de notre élément lumière directionnelle.

2° Ajout de notre élément à la scène.

A ce stade, vous avez encore un écran noir tout moche, mais on va y remédier tout de suite.

Etape 3 Genèse

Accrochez vous car c’est la que la magie opère

//Genèse

   //Création geometry and material Terre

    var earthGeometry = new THREE.SphereGeometry( 5, 50, 50 );

    var earthMaterial = new THREE.MeshPhongMaterial({

        map: new THREE.ImageUtils.loadTexture("/textures/2_no_clouds_4k.jpg"),

        color: 0xaaaaaa,

        specular: 0x333333,

        shininess: 25

    });

    //Création geometry and material Nuages

    var cloudGeometry = new THREE.SphereGeometry(5.05,  50, 50);

    var cloudMaterial = new THREE.MeshPhongMaterial({

        map: new THREE.ImageUtils.loadTexture("/textures/fair_clouds_4k.png"),

        transparent: true,

        opacity: 0.8

    });

    //Création geometry and material Bump

    var bumpGeometry = new THREE.SphereGeometry(5,  50, 50);

    var bumpMaterial = new THREE.MeshPhongMaterial({

        map: new THREE.ImageUtils.loadTexture("/textures/elev_bump_4k.jpg"),

        transparent: true,

        opacity: 0.2,

    });

    //Création geometry and material Etoiles

    var starGeometry = new THREE.SphereGeometry(200, 50, 50);

    var starMaterial = new THREE.MeshPhongMaterial({

        map: new THREE.ImageUtils.loadTexture("/textures/2048x1024.png"),

        side: THREE.DoubleSide,

        shininess: 0

    });

On crée dans l’ordre la terre, les nuages, le bump (relief de la terre) puis les étoiles qui seront en fond.

Je vais vous décrire précisément ce qui se passe lors de la création de la terre. Sachez que c’est exactement la même chose pour les autres éléments.

NB : à ce stade, votre écran est toujours noir car il manque toujours la boucle de rendu finale livrée en étape 4.

Reprenons donc étape par étape la création de l’élément earth. Un élément est constituée de deux éléments :

Une géométry : la structure

var earthGeometry = new THREE.SphereGeometry( 5, 50, 50 );

Ou l’on définit la taille de la terre ainsi que son aspect parfaitement sphérique.

Et un material : le look

 var earthMaterial = new THREE.MeshPhongMaterial({

        map: new THREE.ImageUtils.loadTexture("/textures/2_no_clouds_4k.jpg"),

        color: 0xaaaaaa,

        specular: 0x333333,

        shininess: 25

)}

Le material est ici un MeshPhongMaterial, c’est-à-dire un material qui va affiner ses vertex pour donner un effet de sphère.

Ce material comprend plusieurs propriétés :

  • Une texture : ici j’ai chargé un planisphère de notre bonne vieille terre
  • Une couleur de base
  • Une couleur de réflexion de la lumière
  • L’intensité de la réflexion de la lumière

Et c’est tout. Sachez qu’il existe bien d’autres propriétés Three.js qui sont toutes disponibles dans la doc de la librairie.

Je vous vois d’ici vous languir. Passons au rendu final, que cela resssemble enfin à quelquechose de votre coté.

Etape 4 L’instant rendu.

    //Construction & Ajout du mesh Terre Nuages Bump Etoiles (le mix entre la structure géométrique et la texture) à la scène

    var star = new THREE.Mesh(starGeometry, starMaterial);

    scene.add(star);

    var earth = new THREE.Mesh(earthGeometry, earthMaterial);

    scene.add(earth);

    var clouds = new THREE.Mesh(cloudGeometry, cloudMaterial);

    scene.add(clouds);

    var bump = new THREE.Mesh(bumpGeometry, bumpMaterial);

    scene.add(bump);

    //Orbit Controls

    var orbit = new THREE.OrbitControls( camera, renderer.domElement );

    //Render loop

    var render = function() {

        earth.rotation.y += .0015;

        clouds.rotation.y += .0025;

        clouds.rotation.z += .00125;

        bump.rotation.y += .0015;

        renderer.render(scene, camera);

        requestAnimationFrame(render);

    };

    render();

</script>

</body>

</html>

Dans l’ordre nous avons la fusion (le Mesh) , puis l’ajout de l’ensemble de nos éléments à la scène.

//Construction & Ajout du mesh Terre Nuages Bump Etoiles (le mix entre la structure géométrique et la texture) à la scène

    var star = new THREE.Mesh(starGeometry, starMaterial);

    scene.add(star);

    var earth = new THREE.Mesh(earthGeometry, earthMaterial);

    scene.add(earth);

    var clouds = new THREE.Mesh(cloudGeometry, cloudMaterial);

    scene.add(clouds);

    var bump = new THREE.Mesh(bumpGeometry, bumpMaterial);

    scene.add(bump);

On définit que chaque élément sera un mix entre son material et sa geometry puis on l’ajoute à la scène comme pour la lumière plus haut. Vous vous rappelez ?

Ensuite, on appelle le contrôle d’orbite grâce au petit script que je vous ait fait charger ci-dessus.

    //Orbit Controls

    var orbit = new THREE.OrbitControls( camera, renderer.domElement );

Et pour finir on crée la boucle de rendu finale

    //Render loop

    var render = function() {

        earth.rotation.y += .0015;

        clouds.rotation.y += .0025;

        clouds.rotation.z += .00125;

        bump.rotation.y += .0015;

        renderer.render(scene, camera);

        requestAnimationFrame(render);
    };

    render();

</script>

</body>

</html>

On définit une rotation pour la terre (celle du bump devra être identique) ainsi qu’une rotation différente pour les nuages. (Je joue sur l’axe des z pour donner un effet un peu plus réaliste).

Et voilà le travail ! N’hésitez pas à jouer avec les valeurs pour voir le rendu. Si ce tutoriel vous à plu, j’en ferais un autre un peu plus poussé ou nous ferons tourner la lune autour de la terre et la terre autour du soleil (grosse marrade en perspective).

Si vous voulez voir des trucs incroyables réalisés avec three.js je vous conseille de cliquer ici

Les ressources Js sont téléchargeables ici :

Three.js

Orbit Control

Les images ici :

Terre

Nuages

Bump

Etoiles

Ci-dessous l’ensemble du code que vous pouvez télécharger en haut de page (orbitcontrol bloque la sélection sur la page).

<html>

<head>

    <title>My first three.js app</title>

    <style>

        body { margin: 0; }

        canvas { width: 100%; height: 100% }

    </style>

</head>

<body>

<script src="js/three.js"></script>

<script src="js/OrbitControls.js"></script>

<script>

    //Initialisation//

    var scene = new THREE.Scene();

    var camera = new THREE.PerspectiveCamera( 45, window.innerWidth/window.innerHeight, 1, 1000 );

    var renderer = new THREE.WebGLRenderer();

    renderer.setSize( window.innerWidth, window.innerHeight );

    document.body.appendChild( renderer.domElement );

    camera.position.set(0,0,15);

    //Création de la lumière

    //Ambiante

    var light = new THREE.AmbientLight( 0x888888 );

    scene.add( light );

    //Directionelle

    var light = new THREE.DirectionalLight( 0xfdfcf0, 1 );

    light.position.set(20,10,20);

    scene.add( light );

    //Genèse

   //Création geometry and material Terre

    var earthGeometry = new THREE.SphereGeometry( 5, 50, 50 );

    var earthMaterial = new THREE.MeshPhongMaterial({

        map: new THREE.ImageUtils.loadTexture("/textures/2_no_clouds_4k.jpg"),

        color: 0xaaaaaa,

        specular: 0x333333,

        shininess: 25

    });

    //Création geometry and material Nuages

    var cloudGeometry = new THREE.SphereGeometry(5.05,  50, 50);

    var cloudMaterial = new THREE.MeshPhongMaterial({

        map: new THREE.ImageUtils.loadTexture("/textures/fair_clouds_4k.png"),

        transparent: true,

        opacity: 0.8

    });

    //Création geometry and material Bump

    var bumpGeometry = new THREE.SphereGeometry(5,  50, 50);

    var bumpMaterial = new THREE.MeshPhongMaterial({

        map: new THREE.ImageUtils.loadTexture("/textures/elev_bump_4k.jpg"),

        transparent: true,

        opacity: 0.2,

    });

    //Création geometry and material Etoiles

    var starGeometry = new THREE.SphereGeometry(200, 50, 50);

    var starMaterial = new THREE.MeshPhongMaterial({

        map: new THREE.ImageUtils.loadTexture("/textures/2048x1024.png"),

        side: THREE.DoubleSide,

        shininess: 0

    });

    //Construction & Ajout du mesh Terre Nuages Bump Etoiles (le mix entre la structure géométrique et la texture) à la scène

    var star = new THREE.Mesh(starGeometry, starMaterial);

    scene.add(star);

    var earth = new THREE.Mesh(earthGeometry, earthMaterial);

    scene.add(earth);

    var clouds = new THREE.Mesh(cloudGeometry, cloudMaterial);

    scene.add(clouds);

    var bump = new THREE.Mesh(bumpGeometry, bumpMaterial);

    scene.add(bump);

    //Orbit Controls

    var orbit = new THREE.OrbitControls( camera, renderer.domElement );

    //Render loop

    var render = function() {

        earth.rotation.y += .0015;

        clouds.rotation.y += .0025;

        clouds.rotation.z += .00125;

        bump.rotation.y += .0015;

        renderer.render(scene, camera);

        requestAnimationFrame(render);

    };

    render();

</script>

</body>

</html>

Partager cet article