Qu’est ce que WebGL ?
WebGL, voila une des grandes nouveautés qu’amène HTML5 ! En effet WebGL permet de faire tourner des applications 3D dans votre navigateur sans installation préalable d’un quelconque plugin (Flash ou Java pour ne citer qu’eux).
WebGL est donc un standard de HTML5 qui est déjà pris en charge par de nombreux navigateurs.
Compatibilité de WebGL
Voici une démo que j’ai réalisé et que nous allons mettre en place pas à pas dans ce tutoriel : https://www.info-d-74.com/demos/webGL_CubicVR_HTML5/
A noter que j’ai réussi à la faire tourner uniquement dans Firefox (16.0.2) et Chrome (23.0.1271.95). Sous Opera l’affichage ne se fait pas correctement (bug de textures) et Safari ne prend en charge WebGL qu’à partir de la version 5.2 apparemment. Pour IE8, 9 et 10 il existe IEWebGL qui permet la prise en charge de WebGL. Malheureusement sous IE8 il y a de nombreuses erreurs javascript lors du chargement des librairies CubicVR (peut être que cela fonctionne sous IE9 et 10, je n’ai pas testé).
Un autre point important, WebGL est souvent désactiver par défaut : il vous faut l’activer manuellement. Voici pour chaque navigateur les manipulations à faire :
- FireFox : taper about:config dans la barre d’adresse, puis taper ‘WebGL’ dans la barre de recherche. Mettez true à l’option webgl.force-enabled
- Chrome : activé par défaut il me semble
- Safari : allez dans les préférences puis ‘Avancées’ et cocher ‘Afficher le menu Développement…’. Ensuite allez dans le menu ‘Développement’ et cliquez sur ‘Activer WebGL’
- Opera : taper opera:config dans la barre d’adresse, puis taper ‘WebGL’ dans la barre de recherche. Mettez 1 à l’option Enable WebGL
- Internet Explorer : installez IEWebGL
Télécharger CubicVR
CubicVR est un moteur 3D disponible en Javascript et C++. Je le trouve simple d’utilisation et puissant. Il propose de nombreuses possibilités :
- prise en charge des fichiers 3D Collada (tuto pour plus d’infos)
- gestion de la physique
- prise en charge du bump mapping
- etc…
Nous allons donc l’utiliser dans ce tutoriel pour réaliser la démo vu plus haut. Rendez-vous à cette adresse pour télécharger CubicVR : https://github.com/cjcliffe/CubicVR.js/
Dézipper le contenu de l’archive. Vous pouvez tester les exemples présents dans le dossier samples. Attention pour fonctionner il faut placer les fichiers sur un serveur Web (local ou distant), si vous ouvrez le fichier directement depuis votre disque dur dans votre navigateur cela ne fonctionnera pas.
Charger CubiCVR
Commençons par définir notre page HTML5 et chargeons CubicVR :
<!DOCTYPE html> <head> <meta charset="UTF-8" /> <script type="text/javascript" src="js/ammo.js"></script> <script type="text/javascript" src="js/CubicVR.js"></script> <script type="text/javascript"> function webGLStart() { var gl = CubicVR.init(); var canvas = CubicVR.getCanvas(); var scene = new CubicVR.Scene(canvas.width, canvas.height, 80); } </script> </head> <body onLoad="CubicVR.start('auto',webGLStart);"> </body> </html>
On charge CubicVR et Ammo (qui servira pour la gestion de la physique) et on demande d’initialiser WebGL au chargement de la page. Ensuite on définit la scène avec une caméra qui affichera la scène de la taille du canvas avec un champ vision de 80°.
A ce stade si vous testez vous obtiendrez une page noir qui indique que CubicVR a bien initialisé un canvas WebGL sur toute la page.
Afficher un sphère
Nous allons maintenant ajouter une sphère à la scène. Ajoutez ce code après var scene = new CubicVR.Scene(canvas.width,canvas.height, 80); :
var sphereMat = new CubicVR.Material({ color: [1.0, 0.2, 0] }); var sphereMesh = new CubicVR.Mesh({ primitive: { type: "sphere", radius: 1.5, lat: 60, lon: 60, material: sphereMat }, compile: true }); var sphereObject = new CubicVR.SceneObject({mesh:sphereMesh, position:[0,0,0]}); scene.bindSceneObject(sphereObject); scene.camera.position = [-10, 0, 0]; scene.camera.target = [0, 0, 0]; CubicVR.setGlobalAmbient([1.0,1.0,1.0]); CubicVR.MainLoop(function(timer, gl) { scene.render(); });
On définit un matériau avec une couleur Orange pour la sphère ([1.0, 0.2, 0]).
On crée ensuite la sphère avec un rayon de 1.5, latitude et longitude de 60 et on l’ajoute à la scène en position 0, 0, 0. La caméra est ensuite placer en -10, 0, 0 et regarde vers la sphère (0, 0, 0). Enfin on définit une lumière ambiante blanche (sinon on ne verra rien…) et on spécifie affiche le rendu de la scène. Voilà le résultat que vous devez obtenir :
Ajoutons maintenant une texture pour rendre notre sphère plus jolie. Voici la texture que nous allons utiliser : Texture metal
Modifions note code comme ceci :
var sphereMat = new CubicVR.Material({ textures: { color: "textures/metal.png" } }); var sphereMesh = new CubicVR.Mesh({ primitive: { type: "sphere", radius: 1.5, lat: 60, lon: 60, material: sphereMat, uvmapper: { projectionMode: CubicVR.enums.uv.projection.CUBIC, scale: [3, 3, 3] } }, compile: true });
On donne donc notre texture au matériau au lieu d’une simple couleur et on ajoute le paramètre uvmapper à la création de la sphère. Ce paramètre permet à CubicVR de savoir comment appliquer la texture sur l’objet. A noter que pour une raison que j’ignore le résultat est plus jolie avec le projectionMode en mode CUBIC plutôt que SPHERICAL (tester avec CubicVR.enums.uv.projection.SPHERICAL vous verrez). Modifiez le scale permet de changer la taille de la texture sur l’objet. Voila le résultat :
Afficher un sol et gérer la physique
Ajoutons maintenant un sol au dessous de notre sphère. Voici la texture que nous allons utiliser : Texture carrelage
Ajouter ce code après scene.bindSceneObject(sphereObject); :
var solMat = new CubicVR.Material({ textures: { color: "textures/carrelage.png" }, }); var solUV = { projectionMode: "cubic", scale: [0.25, 1, 0.25] }; var solMesh = new CubicVR.Mesh({ primitive: { type: "box", size: 1.0, material: solMat, uvmapper: { projectionMode: "cubic", scale: [0.25, 1, 0.25] } }, compile: true }); var solObject = new CubicVR.SceneObject({mesh:solMesh, scale: [50, 1, 50], position:[0, -10, 0]}); scene.bindSceneObject(solObject);
De la même manière que pour la sphère nous créer le sol mais type box (boite). On lui définit une taille de 50x1x50 et on le place juste en dessous de la sphère (0, -10, 0). Le scale du uvmapper permet de réduire la texture pour qu’elle ne soit pas trop grande sur les axe x et z (0.25, 1, 0.25) :
Ajouter maintenant la gestion de la physique. Notre sphère devrait tomber sur le sol suivant la loi de la gravité. Voici comment faire (à ajouter juste après le code précédant) :
var physics = new CubicVR.ScenePhysics(); var rigidSphere = new CubicVR.RigidBody(sphereObject, { type: "dynamic", mass:400, collision: { type: "sphere", mesh: sphereMesh, radius: 1.5 } }); physics.bind(rigidSphere); var rigidFloor = new CubicVR.RigidBody(solObject, { type: "static", mass: 0, collision: { type: "box", size: solObject.scale } }); physics.bind(rigidFloor);
On définit pour la sphère un ‘corps rigide’ dynamique (elle peut bouger), d’une masse de 400 et son type de collision est sphere. Pour le sol c’est pareil sauf qu’il est statique (il ne bouge pas), qu’il ne possède pas de masse et que son type de collision est de type box. Il ne reste plus qu’a ajouter la prise en compte de la physique dans le MainLoop :
CubicVR.MainLoop(function(timer, gl) { physics.stepSimulation(timer.getLastUpdateSeconds()); scene.render(); });
Si vous testez votre sphère doit tomber sur le sol.
Dernière étape : mur de briques et cône
Pour terminer nous allons ajouter un mur de brique et faire en sorte que la sphère aille taper dedans. Pour cela nous allons dévier sa trajectoire à l’aide d’un cône placé en dessous de la sphère.
Commençons déjà par créer notre mur de brique : Texture brique
Voila le code :
var WALL_WIDTH = 10; var WALL_HEIGHT = 10; var briqueMat = new CubicVR.Material({ textures: { color: "textures/brique.png" } }); var briqueMesh = new CubicVR.Mesh({ primitive: { type: "box", size: 1.0, material: briqueMat, uvmapper: { projectionMode: CubicVR.enums.uv.projection.CUBIC, scale: [3, 1, 1] } }, compile: true }); for(var i=0; i<WALL_WIDTH; i++) { for(var j=0; j<WALL_HEIGHT; j++) { var briqueObject = new CubicVR.SceneObject(briqueMesh); var briqueObj = new CubicVR.SceneObject({ mesh: briqueMesh, scale: [1, 1, 3], position: [10, -9+i, j*3-13.5] }); scene.bindSceneObject(briqueObj); var rigidBox = new CubicVR.RigidBody(briqueObj, { type: "dynamic", mass:4, collision: { type: CubicVR.enums.collision.shape.BOX, mesh: briqueMesh, size: briqueObj.scale } }); physics.bind(rigidBox); } }
On crée un mur de 10×10 briques derrière la sphère. Les briques ont une masse de 4 et sont soumises aux collisions. Ce qui veut dire que quand la sphère rentrera en collision elles vont subir la poussée de la sphère.
Il ne nous reste plus qu’a créer notre cône pour dévier la sphère lorsqu’elle tombe :
var coneMesh = new CubicVR.Mesh({ primitive: { type: "cone", base: 6, height: 6, material: sphereMat, uvmapper: { projectionMode: "cubic", scale: [3, 3, 3] } }, compile: true }); var coneObject = new CubicVR.SceneObject({mesh:coneMesh, position:[-1,-7,0]}); scene.bindSceneObject(coneObject); var rigidCone = new CubicVR.RigidBody(coneObject, { type: "static", mass:0, collision: { type: CubicVR.enums.collision.shape.CONE, radius: 6, height: 6, mesh: coneMesh } }); physics.bind(rigidCone);
Le cône est défini comme static (il ne bougera pas). Voilà le résultat que nous obtenons :
Nous pouvons ajouter une dernière chose : la possibilité de tourner la caméra à la souris.
Ajoutez simplement cette ligne à la fin :
mvc = new CubicVR.MouseViewController(canvas, scene.camera);
Voila nous en avons terminé avec ce tutoriel. J’espère que j’ai été assez clair dans les explications et que cela vous sera utile. N’hésitez pas envoyer vos remarques.
Ressources sur WebGL et CubicVR :
- Éditeur de terrain : http://cjcliffe.github.com/CubicVR.js/experiment/landscape_editor/landscape_edit_500m.html
- Blog sur WebGl (en anglais) : http://learningwebgl.com/blog/
- très bon tuto sur Blender et WebGL : Blender to WebGL