Archives de catégorie : Démos webgl

Effet d’eau pour webglparis.com

Un effet de simulation d’eau fait office d’arrière plan sur le site internet de WebGL Paris, http://www.webglparis.com . Pour réaliser cet effet nous simulons les équations de Saint Venant (Shallow Water Equations) en GPGPU dans le shader de fragments en utilisant une texture flottante de 512X512 pixels.

La simulation est réalisée 4 fois par image rendue, soit à un rythme de 4*60=240 pas par seconde pour un affichage à 60Hz.

Après le chargement de la page, les positions et les tailles de différents éléments de la page (ayant la classe CSS .obstacle) sont récupérées en javascript avec l’aide de JQuery. Un canvas2D est alors dessiné pour faire office de heightmap.

Une normal map est calculée côté GPU, après avoir préalablement appliqué un flou gaussien sur la heightmap.

Le rendu final est assez léger, peu perturbant pour l’oeil, et il répartit la teinte d’une façon intéressante sur la page. Seul bémol : pour les configuration n’ayant pas l’extension WebGL OES_TEXTURE_FLOAT, les vagues sont légèrement trop marquées.

Une vidéo de l’effet :

WebGL tiny background water effect
Runtime
0:37
Compteur de vues
237

 

WebGL 1K demo

fnacap6

WebGL est réputé pour être lourd à mettre en oeuvre. Effectivement développer un simple cube tournant coloré nécessite beaucoup de lignes de code.

Mais pour jouer avec les mathématiques et calculer la couleur des pixels parallèlement, dans le but de créer des visualisations sympathiques, webGL peut s’avérer imbattable.

Pour preuve, une démo WebGL de 1024 caractères, soit 1KO :

<body style=’margin:0onload= »m=’;varying float x,y;void main(void){‘,w=window,c=document.getElementById(‘c’);k=c.getContext(‘webgl’);r=k.createBuffer;y=c.width=w.innerWidth,z=c.height=w.innerHeight;f=k.createProgram(),x=function(o,l){n=k.createShader(l);k.shaderSource(n,o);k.compileShader(n);k.attachShader(f,n);return n};x(‘attribute vec2 p’+m+’x=p.x;y=p.y;gl_Position=vec4(p,0.,1.);}’,35633),x(‘precision lowp float;uniform float t’+m+’gl_FragColor=vec4(mod(floor(t-x*pow(x*x+y*y,-1.5))+floor(t-y*pow(x*x+y*y,-1.5)),2.)+vec3(0.,.4,.8), 1.);}’,35632);k.linkProgram(f);j=k.getUniformLocation(f,’t’);b=k.getAttribLocation(f,’p’),k.enableVertexAttribArray(b);k.useProgram(f);q=function(n,p){v=k.createBuffer();k.bindBuffer(p,v);k.bufferData(p,n,35044)};q(new Float32Array([-1,-1,1,-1,1,1,-1,1]),34962);q(new Uint16Array([0,3,1,2]),34963);k.viewport(0,0,y,z);d=function(l){k.clear(16384);k.uniform1f(j,l*.001);k.vertexAttribPointer(b,2,5126,0,8,0);k.drawElements(5,4,5123,0);w.requestAnimationFrame(d)};d()« ><canvas id=’c‘/>

Je me suis permis le luxe de placer des balises HTML, et de les compter dans le total. Je n’utilise pas les balises <!DOCTYPE html>, <html>, je ne précise pas l’encodage des caractères et je ne ferme pas les balises <body>, <html>. Je n’utilise pas de var pour déclarer les variables et j’oublie volontairement GL.flush() à la fin de la boucle de rendu. La déclaration du code dans la propriété onload de la balise body n’est pas chaleureusement conseillée par le W3C. Mais les navigateurs modernes sont très tolérants,  alors il faut en profiter !

La démo est entièrement codée en caractères texte normaux. En effet, je considère qu’utiliser des jeux de caractères étendus/compresser tout le code de façon plus qu’incompréhensible n’est pas fair play.

La démo est accessible à partir du site de Webgl Academy : Démo Webgl 1K

 

Simulation de tissus

Nous avons réalisé une démo de simulation de tissu sur GPU. Elle est disponible ici : simulation de tissu webgl . Elle représente un carré de tissu, modélisé par un réseau de masses liées les unes aux autres par des ressorts/amortisseurs. Le réseau comporte 62500 points, et tous les calculs des champs du réseau (vitesses, position) sont effectués en parallèle, côté GPU dans le shader de fragments. En plus des forces exercées par les ressorts, chaque point est soumis à la gravité et à une force de frottement, dont la composante normale est séparée et plus élevée que la composante tangentielle.

Des collisions entre le tissu et des cylindres sont calculées, avec un coefficient de frottement statique et dynamique.

Cette simulation utilise différentes extensions webgl : les texture flottantes (OES_texture_float – qui permet de stocker des données dans des textures sur 16 bits au lieu de 8), l’indexage des tableau d’éléments sur 32 bits, qui permet d’avoir plus de 2^16 points dans un unique maillage (OES_element_index_uint), le filtrage de texture anisotropique pour un meilleur rendu lorsque le tissu est affiché en biais (EXT_texture_filter_anisotropic), et enfin la possibilité d’avoir plusieurs buffers de rendu dans un même framebuffer (WEBGL_draw_buffers).

La dernière extension, WEBGL_draw_buffers, est encore très expérimentale. Elle permet de lier un framebuffer à plusieurs buffers de rendu, eux-même liés à des textures. Ensuite il est possible de dessiner dans le i-ème buffer de rendu dans le shader de fragments en remplaçant la variable de sortie gl_FragColor par gl_FragData[i].

Il serait possible de se passer de cette dernière extension moyennant quelques passes supplémentaires dans le rendu, et plus de lignes de code.

Pour exécuter la démo,

– utilisez Chrome 29 ou supérieur. Pour afficher votre version de Chrome, cliquez sur l’icône en haut à droite, puis sur « A propos de Google Chrome » :

A l’heure ou j’écris ces lignes, cette version de Chrome est encore en version béta.

– Activez les extensions expérimentales de WebGL. Pour celà tapez dans la barre d’URL : chrome://flags . Puis cliquez sur « activer les extensions  WebGL brouillon » :

– Fermez Chrome. Si vous utilisez Linux, relancez Chrome et testez la démo. Si vous utilisez Windows, il sera nécessaire de désactiver ANGLE sous Chrome. ANGLE est une implémentation d’OpenGL ES2 redirigeant tous les appels de WebGL vers DirectX. Pour désactiver Angle sous Chrome, cliquez du bouton droit sur votre lien vers Chrome, puis ajoutez –use-gl=desktop à la fin de la cible :

Enfin, lancez Chrome à partir du lien ainsi modifié et testez la démo 🙂 .

Moteur physique sur GPU basé sur le Cubemapping

Habituellement les moteurs physique WebGL ( ce qui empêche le joueur de passer à travers le décor ) tournent sur le CPU (Central Processing Unit) et non sur le GPU (Graphic Processing Unit).

Dans les applications compilées, la physique peut être calculée sur GPU, soit en utilisant des shaders comme le geometry shader auxquels on n’a pas accès en WebGL, soit en utilisant des fonctionnalités matérielles spécifiques, comme PhysX pour les carte graphiques Nvidia. Mais pour les applications WebGL, la physique est ramenée à des collisions sphère/octree calculées sur CPU.

L’octree (arbre contenant toutes les faces de la scène) est soit pré-calculé et inclus dans les données, soit calculé lors du chargement de la scène. Dans tous les cas, il alourdit le chargement. Quant au moteur physique en Javascript, il requiert beaucoup de calculs de collisions pour chaque image générée.

Je détaille le fonctionnement d’un tel moteur physique dans mon ouvrage WebGL : Guide de programmation d’applications web 3D.

Je présente ici une façon très différentes de calculer la physique. Elle ne nécessite ni de calcul d’octree, ni de calcul d’intersections sur CPU via des méthodes dérivées de l’utilisation des coordonnées de Plücker et du théorême de l’axe séparateur. Presque tout est effectué sur le GPU.

Capture d’écran de la démonstration :

Capture d'écran de la démonstration du moteur physique basé sur le cubemapping

Capture d’écran de la démonstration disponible sur http://spacegoo.com/publis/cubemapPhysics/implementation

Cliquez ici pour lire la publication détaillant le fonctionnement de l’algorithme (en anglais)

Cliquez ici pour jouer à la démonstration (utilisez les flèches du pavé directionnel du clavier pour vous déplacer, et la barre d’espace pour sauter),

Cliquez ici pour télécharger le code source de la démonstration

Cet algorithme est intéressant à implémenter pour des applications où la physique se résume à des collisions personnage/décor. S’il y a de nombreuses interactions physiques à calculer (interactions objet-objet notamment), il vaudra mieux passer par des algorithmes plus classiques basés sur l’utilisation d’octree.

frontoffice 3D pour wordpress

Nous avons créé une interface 3D pour un site vitrine ou un blog wordpress.

Les images d’arrière-plan, le contenu texte, le titre… sont tous facilement modifiables en passant par le backoffice wordpress. Les modèles sont également changeables.

Nous nous sommes basés sur Three.js, et nous avons également utilisé JQUERY et JQUERY-UI.

La démonstration est visible ici : Interface 3D pour wordpress