CULTURE • Introduction aux principes fondamentaux du WebGL

Ça c'est le menu, comme au restaurant

CULTURE • Introduction aux principes fondamentaux du WebGL

25.07.24

Initiation à
l’API 3D WebGL

Attention : cerveau qui chauffe ! 🧠

Dans cet article, nous allons explorer les principes fondamentaux de WebGL, une technologie puissante qui permet de créer des graphiques 3D interactifs directement dans les navigateurs web. Que vous soyez un développeur débutant ou simplement curieux de comprendre comment fonctionnent les animations 3D sur le web, cet article vous guidera à travers les concepts de base de WebGL de manière claire et accessible. L’objectif est de démystifier cette technologie afin que chacun puisse apprécier son potentiel et, pourquoi pas, l’implémenter dans ses propres projets créatifs.

Brève présentation de l’API WebGL

Qu'est-ce que l'infographie tridimensionnelle ?

L'infographie tridimensionnelle (3D) est une technique utilisée pour créer des images numériques qui ont l'apparence de la profondeur et du volume. Contrairement aux images 2D, qui ne montrent que la hauteur et la largeur, les images 3D ajoutent une troisième dimension, la profondeur, ce qui permet de représenter des objets de manière plus réaliste. L’infographie tridimensionnelle est une technique essentielle dans de nombreux domaines créatifs et techniques, offrant des possibilités infinies pour la visualisation et l'interaction.

Présentations des API de rendu 3D

Une API 3D est une interface de programmation qui permet aux développeurs de créer, manipuler et rendre des graphiques tridimensionnels. Ces API fournissent un ensemble de fonctions et de commandes standardisées que les développeurs peuvent utiliser pour dessiner des objets 3D, gérer l'éclairage, les textures, les animations et les effets visuels dans leurs applications. Les API rendent le développement plus facile en cachant la complexité technique et en fournissant des fonctions simples que les développeurs peuvent utiliser sans avoir à comprendre les détails techniques.

Les principales API 3D incluent OpenGL, une API multiplateforme utilisée pour le rendu 2D et 3D dans les jeux vidéo et les simulations scientifiques, et Direct3D, une composante de DirectX optimisée pour les systèmes Windows. Vulkan, développée par le Khronos Group, offre un contrôle de bas niveau sur le matériel graphique pour des performances accrues. Metal, d'Apple, fournit des performances élevées sur iOS et macOS. WebGL permet le rendu 3D dans les navigateurs web sans plugins supplémentaires, facilitant le développement d'applications interactives.

Liste des principales librairies API 3D

Rétrospective de WebGL

WebGL est une API web basée sur l’API OpenGL (Open Graphics Library). Introduit en 2011, WebGL est basé sur OpenGL ES 2.0, une version allégée d'OpenGL sortie en 2007 et initialement conçue pour les appareils mobiles. En exploitant la puissance du GPU (processeur graphique), cette API permet de créer des graphiques 3D interactifs et des animations complexes directement dans le navigateur, enrichissant l'expérience utilisateur.

Les librairies WebGL

Des librairies JavaScript ont été développées pour simplifier le développement d'applications 3D. Parmi les plus connues figurent Three.js, la plus connue d’entre-elles, Babylon.js , et OGL, cette dernière se distinguant par sa légèreté et sa simplicité. Ces librairies permettent de tirer pleinement parti de WebGL pour créer des expériences web immersives et performantes.

Liste des principales librairies WebGL

Exemple de projet WebGL

Nous avons récemment mis en ligne le portfolio du collectif créatif Rodeo. En utilisant l'API WebGL pour concevoir la grille de projets, nous avons pu intégrer des animations fluides et des effets visuels poussés. Cet exemple illustre parfaitement les capacités d'animation offertes par WebGL.

Visuel de la grille de projets infinie du site rodeo.film

Pourquoi apprendre le WebGL from scratch du coup ?

La question que l’on peut se poser est la suivante : quel intérêt d’apprendre le vanilla WebGL si ces librairies existent ? Il existe plusieurs points qui peuvent justifier un apprentissage plus poussé de l’API sans passer par ces librairies :

  • Utiliser les librairies sans compréhension des concepts fondamentaux de WebGL peut très rapidement amener à des complexifications lors de la phase de développement. Une connaissance approfondie du vanilla WebGL facilite le débogage et l'optimisation des performances, car vous comprenez mieux ce qui se passe sous le capot. Apprendre les bases de WebGL vous donne une base solide pour comprendre et utiliser efficacement les librairies 3D comme Three.js ou Babylon.js, mais permet aussi d’avoir des bases solides pour apprendre d'autres API graphiques comme OpenGL ou Vulkan.
  • Bien qu’elles soient très utiles et complètes, les librairies javascript sont lourdes. Il est parfois plus simple et efficace de réaliser certains projets directement en utilisant le vanilla WebGL, sans avoir recours à ces librairies. Se passer de librairies peut alléger énormément de poids sur votre fichier javascript final. Par exemple, Three.js pèse 671 kB (173 kB gzip), Babylon peut aller jusqu’à 5.03 MB (1.09 MB gzip) tandis qu’OLG ne pèse "que" 126 kB (37.4 kB gzip).

Approche théorique et technique de WebGL

L'objectif de cette section est de vous guider, étape par étape, pour afficher votre premier triangle en utilisant l'API WebGL sur une page web. Créer ce triangle est l'équivalent du traditionnel "Hello world" dans un langage de programmation. Bien que cela puisse sembler trivial, vous découvrirez rapidement que la création d'un simple triangle en WebGL comporte quelques défis intéressants à relever !

Présentation de la pipeline de rendu WebGL

Plusieurs étapes sont nécessaires à la réalisation d’un rendu 3D en WebGL. Ces étapes peuvent être regroupées en six parties :

  1. Génération et traitement des données : Nous générons et traitons nos données en JavaScript, puis nous les transmettons au GPU (processeur graphique).
  2. Création des points dans l’espace : Le GPU traite les données pour créer des points dans l’espace (les sommets). Ces points peuvent ensuite être reliés pour former des formes ou objets vectoriels.
  3. Transformation des formes vectorielles : Les formes vectorielles générées sont transformées et positionnées dans l’espace 3D à l'aide des shaders de vertex.
  4. Rasterisation : Les formes vectorielles sont ensuite converties en pixels via le processus de rasterisation, qui détermine quels pixels de l'écran représentent les formes.
  5. Coloration des pixels : Avant d'afficher les pixels, chaque pixel est coloré en fonction de la couleur, de la texture, des ombres et des lumières appliquées dans la scène. Cela se fait à l'aide des shaders de fragment.
  6. Affichage : Les pixels colorés sont finalement renvoyés à l’écran, permettant ainsi d’afficher l’image rendue.
Schémas de la pipeline de rendu 3D (credit: open.gl)

Ces étapes forment la pipeline de rendu WebGL, un processus complexe mais essentiel pour afficher des graphiques 3D interactifs dans le navigateur.

En tant que développeur, nous n'avons pas besoin de nous occuper de toutes ces étapes. Notre travail consiste principalement à fournir les instructions au GPU pour les étapes de "Vertex Shader" et "Fragment Shader". Les autres étapes sont gérées automatiquement par le GPU.

Le Vertex Shader intervient au début de la pipeline de rendu graphique, après que les données des sommets (vertex data) ont été envoyées au GPU depuis le programme JavaScript. Il intervient entre l'étape 1 et l'étape 2 du processus de rendu et transforme les coordonnées des sommets, applique des transformations et des calculs d'attributs, et prépare les sommets pour les étapes suivantes du rendu 3D.

Le Fragment Shader intervient quant à lui plutôt vers la fin de la pipeline, après la rasterisation pour déterminer la couleur finale de chaque fragment avant leur affichage sur l'écran.

(credit: unsoundscapes.com)

Le système de coordonnée en WebGL

En WebGL, les coordonnées sont normalisées pour aller de -1 à +1 quelle que soit la taille du canvas. Cela signifie que le point (-1, -1) correspond au coin inférieur gauche du canvas et le point (+1, +1) au coin supérieur droit. Cette normalisation permet de travailler indépendamment de la résolution ou des dimensions spécifiques du canvas, facilitant ainsi le rendu et les transformations des objets 3D. Les coordonnées du centre du canvas sont (0, 0).

Schémas du système de coordonnées en WebGL

Approche technique: Préparation du code HTML

Pour commencer à utiliser WebGL, un simple élément HTML <canvas> suffit dans votre fichier index.html. Cet élément sert de surface de rendu sur laquelle WebGL dessine les graphiques 3D. En ajoutant un <canvas> à votre page HTML, vous créez l'espace nécessaire pour que WebGL puisse fonctionner.

Approche technique: Préparation du canvas

Du côté JavaScript, on récupère notre element canvas et on lui applique une hauteur et une largeur. Pour avoir la même taille sur différents écrans, on multiplie la hauteur et la largeur de l’écran par le “devicePixelRatio” (1 par défaut, +2 pour les écrans retina apple). Pour terminer avec le canvas, on lui définit un contexte. Il existe plusieurs contextes selon la technologie que l’on souhaite utiliser (2d, webgl, webgpu, bitmaprenderer, etc). Nous allons dans notre cas choisir le contexte “webgl”.

Création des points de notre triangle

Pour générer notre triangle, nous devons définir des points. Dans un espace 3D, un point a trois coordonnées géographiques (x, y, z). Les points fournis par le JavaScript au GPU sont plus communément appelés "vertices". Un triangle est composé de trois points. Ces vertices seront transmises au programme pour la création de notre rendu 3D.

Pour cet exemple, nous allons utiliser un triangle basé uniquement sur les axes X et Y (2 coordonnées par vertex). Nos coordonnées ne sont pas stockées dans un array standard mais dans un Float32Array, qui n'accepte que des valeurs de type float et int. WebGL n'accepte pas les arrays classiques.

Définition des couleurs des points

Nous allons également associer une couleur à chaque point de notre triangle. Notez qu'en WebGL, les valeurs de couleur vont de 0 à 1, plutôt que de 0 à 255 comme en RGB. Ainsi, une couleur RGB de 255 correspond à 1 en WebGL.

Création des Vertex et Fragment shaders

Une fois les données créés, nous devons indiquer au programme comment les utiliser pour générer un rendu 3D. Pour cela, nous allons écrire deux shaders en GLSL, le langage de programmation de WebGL : un vertex shader pour l'étape de transformation des vertices et un fragment shader pour l'étape de coloration des fragments. Ces shaders auront accès aux données fournies par le JavaScript.

Chaque point va exécuter le programme (vertex et fragment) en parallèle.

Vertex: Positionnement des points dans l’espace

Durant cette étape, on récupère les données de positions et de couleurs pour ce point et on affecte la valeur position à la variable gl_Position (x, y, z, w).

Fragment: Définition de la couleur final du pixel

Pendant l'étape fragment, on récupère la valeur vColor fournie par le vertex shader et on affecte cette valeur à la variable de type vec4 gl_FragColor (r,g,b, a).

Créations des fonctions helpers

Nous allons clarifier la fonction renderFrame en créant deux fonctions : createProgram et createShader.

La fonction createProgram crée et lie un programme WebGL en combinant le vertex et le fragment shader. Elle initialise un nouveau programme, attache les deux shaders, les lie ensemble, et vérifie si l'opération a réussi. Elle retourne le programme prêt à être utilisé.

La fonction createShader crée et compile un shader WebGL à partir du type spécifié (vertex ou fragment) et de son code source. Elle initialise un shader, lui associe le code source, puis le compile. Elle retourne le shader prêt à être utilisé.

Les fonctions createShader et createProgram sont essentielles pour préparer et lier les shaders dans WebGL. Ensemble, elles permettent de définir et d'exécuter les opérations de rendu graphique en WebGL.

Création des buffers pour nos données

Une fois les shaders créés, nous devons indiquer au programme comment les utiliser pour générer un rendu 3D. Les données que nous souhaitons fournir à notre programme sont prêtes côté JavaScript. Il faut désormais les transmettre au programme. Pour cela, nous allons créer un buffer.

Un buffer est une zone de mémoire utilisée pour stocker temporairement des données pendant leur transfert. En WebGL, un buffer sert à faire transiter des données du CPU (processeur central) vers le GPU (processeur graphique).

Création de la fonction de rendu 3D

Une fois que le GPU est prêt à recevoir les données et que nos données sont bien formatées, nous pouvons exécuter la fonction de rendu renderFrame qui affichera notre image sur le canvas.

Cette étape consiste à lier les buffers au GPU et à lui donner les instructions sur ce qu'il doit lire et comment le lire pour effectuer le rendu. Dans cet exemple, nous expliquons au GPU comment gérer nos données pour positionner et colorer les points dans l’espace, avant de réaliser le rendu et de l’afficher dans le canvas.

Dans la première partie du code, nous allons effacer le contenu de l'element canvas avant de lui appliquer une couleur de fond avant la création de notre rendu 3D (ici un gris foncé).

Nous allons ensuite préparer le GPU afin qu'il se prépare à recevoir et à traiter les données des positions des vertices pour le rendu 3D. La même chose est faite pour le traitement des couleurs.

Et enfin les dernières lignes finalisent le processus de dessin d'un rendu 3D. Il configure les buffers nécessaires, active le programme de dessin avec les shaders appropriés, et envoie une commande au GPU pour effectuer le rendu final à l'écran.

Voila, notre triangle est visible !
Nos troa points ont été positionnés puis connectés dans l’espace pour former un triangle.
Pour chaque point, une couleur a bien été attribué et rendu. Automatiquement, les couleurs ont été interpolé par le GPU et a généré ce dégradé de couleur.

Comment aller plus loin …

Après avoir créé votre premier triangle en WebGL, vous pouvez approfondir vos compétences en explorant des formes plus complexes. Voici quelques idées pour enrichir vos projets WebGL :

  • Créer des formes plus complexes en combinant plusieurs triangles. Par exemple, un carré peut être formé de deux triangles. En maîtrisant cette technique, vous pourrez modéliser des objets 3D plus élaborés et explorer des concepts avancés comme les textures et les transformations.
  • Ajouter de la dimension à vos vertices et passez d'un espace 2D à 3D en incluant une coordonnée supplémentaire (z) pour chaque vertex. Cela permet de positionner vos objets dans un espace tridimensionnel.
  • Animer les données, telles que les positions et les couleurs, en utilisant des bibliothèques d'animation comme GSAP ou anime.js. Cela permet de créer des expériences interactives et dynamiques en ajustant en temps réel l'apparence et le mouvement des objets 3D.

ça t'a plu? Plus d'articles

T'es encore sur IE ? Passes à un autre navigateur (à jour) afin de profiter des dernières technologies.

VOIR