Skip to content

Modelisation5ETI/WebGL_Intro

Repository files navigation

##TP Introduction to WebGL

Lucas Gandel et Danaële Puechmaille - CPE Lyon - 5ETI


Visualize page (1) or Visualize page (2)

License : Apache 2.0.


Objectifs


Le but du TP est d'apprendre à utiliser WebGL, une API Javascript de rendu interactif 3D et 2D compatible sur la plupart des navigateurs web. L'objectif du projet est de créer une scène interactive 3D utilisant la technologie WebGL. La scène doit contenir des intéractions physiques. Ce projet nous as permis d'utiliser nos connaissances en programmation OpenGL afin de s'adapter à l'outil WebGL qui utilise des techniques similaires de rendu (mesh, texture, illumination). Finalement, ce TP nous permet aussi d'exposer ce projet à de futurs recruteurs au cours de notre recherche de stage de fin d'étude.


Implementation


Nous avons réalisé une scène représentant un planisphère en relief sur lequel une sphere roule et rentre en collision avec les montagnes. L'utilisateur peut déplacer la sphère avec les flèches du clavier et peut ajouter un effet d'eau en mouvement sur l'océan avec la touche "w" du clavier. La barre d'espace permet de réinitialiser la position de la sphère.

La scène est composée d'éléments disponibles nativement dans Babylon.js afin de mettre en évidence l'étendue des possibilités qu'offre WebGL. Nous utilisons également l'extension waterMaterial de Babylon.js pour un rendre un effet d'eau en mouvement.

Scène

La scène est créée dans la fonction createScene() dans le script javascript du ficher HTML index.html. On utilise cannon.js pour la gestion des collisions et de la physique. Un vecteur de gravité d'une valeur de -9.81 est appliqué continuellement selon l'axe y :

Gestion de la physique :

    var gravityVector = new BABYLON.Vector3( 0,-9.81, 0 );
    var physicsPlugin = new BABYLON.CannonJSPlugin();
    scene.enablePhysics( gravityVector, physicsPlugin );

La prise en charge de cannon.js par Babylon.js permet la gestion de la physique simplement en ajoutant des imposteurs aux maillages. Il est ensuite possible d'appliquer des forces à ces objets, par exemple lorsqu'une touche est activée, ou encore en résultat d'une collision. L'utilisation d'imposteurs permet de représenter des maillages simplifiés afin de faciliter la détection de collision.

Creation de maillages simples :

Des maillages simples tels que le cube, la sphère ou encore le cylindre sont disponibles :

  BABYLON.Mesh.CreateSphere( "sphere", //Label
                             10,       // Nombre de segments
                             10,       // Rayon
                             scene );  // Scène

La sphère constitue le personnage principal de la scène et elle peut être déplacée à l'aide des touches directionnelles du clavier. Il est alors nécessaire d'assigner un imposteur à celle-ci:

  sphere.physicsImpostor = new BABYLON.PhysicsImpostor( sphere,
    BABYLON.PhysicsImpostor.SphereImpostor,     // Type d'imposteur
    { mass: 1, restitution: 0, friction: 0.1 }, // Paramètres physiques
    scene );                                    // Scène

La friction entraine la rotation de la sphère est rend son déplacement réaliste lors de l'ajout d'une impulsion selon une direction.

Il est également possible d'ajouter un matériau au maillage. Dans notre cas, on créé un matériau standard auquel on applique une texture :

  var sphereMaterial = new BABYLON.StandardMaterial( "sphere", scene );
    sphereMaterial.diffuseTexture = new BABYLON.Texture( "data/earth.jpg", scene );
    sphere.material = sphereMaterial;

Terrain :

Babylon.js permet nativement de créer un terrain à partir d'une carte de hauteurs :

 BABYLON.Mesh.CreateGroundFromHeightMap( "ground", // Label
   "data/worldHeightMap.jpg", // Heightmap
   200, 200,                  // largeur, longueur
   250,                       // Nombre de subdivisions
   0, 10,                     // Hauteur min, Hauteur max
   scene,                     // Scene
   false,                     // Mise à jour
   function()                 // Ajoute un imposteur pour les collisions
   {
     ground.setPhysicsState(BABYLON.PhysicsEngine.HeightmapImpostor, { mass: 0 });
   } );

Dans notre scène la carte des hauteurs correspond à l'image de la texture du terrain afin de rendre la scène réaliste.

On note l'ajout de l'imposteur nécessaire à la collision grâce à la fonction passé en paramètre. Elle est appelée lors de la génération du terrain, afin de générer un imposteur à partir de la carte de hauteurs.

Pour de pouvoir visualiser le projet sous Firefox, nous étions contraints d'utiliser une longueur inférieure ou égale à la largeur. En effet, il semblerait que la façon dont Firefox charge les textures peut devenir très couteuse et donner lieu à des erreurs :

Error: WebGL: texImage2D: Chosen format/type incured an expensive reformat: 0x1908/0x1401

Certains comportement similaires pour d'autres projets sont expliqués ici.

Skybox :

On ajoute une Skybox afin de créé un environnement autour de la scène. La skybox est créée à partir d'un cube que l'on texture à l'aide de la méthode suivante :

BABYLON.CubeTexture( rootUrl, scene, extensions, noMipmap, files )

Cette fonction permet de charger les six textures de la skybox. 'rootURL' correspond à la racine du nom des textures. Les extensions par défaut sont :[_px.jpg, _py.jpg, _pz.jpg, _nx.jpg, _ny.jpg, _nz.jpg].

Lumière

Un soleil est modélisé à l'aide d'un maillage sphère et d'une Spotlight. Une trajectoire circulaire est appliquée à l'ensemble afin de visualiser le changement des ombres au sein de la scène.

Materiau océan :

L'océan (qui peut être ajouté avec la touche 'w'), est constitué d'un plan auquel on applique un matériau d'effet d'eau. Ce matériau est disponible dans Babylon.js en incluant le script 'Babylon.js-master/materialsLibrary/dist/babylon.waterMaterial.js'.

Le matériau eau reflète la skybox et le terrain. Les paramètres de vent, hauteur des vagues, couleur etc. on été réglé afin d'obtenir une scène la plus réelle possible.

Cependant, l'ajout de ce matériau est très coûteux en calcul graphique(réflection de l'eau) et il entraine une baisse de la fluidité des déplacements de la sphère.

Rendu final avec un effet d'eau en mouvement

screenshot