WebGL - Pipeline de rendu graphique

Bonjour à tous, aspirants programmeurs ! Aujourd'hui, nous allons entreprendre un voyage passionnant à travers le pipeline de rendu graphique WebGL. Ne vous inquiétez pas si vous êtes nouveaux en programmation - je serai votre guide amical, et nous avancerons pas à pas. À la fin de ce tutoriel, vous aurez une compréhension solide de la manière dont WebGL transforme votre code en visuels époustouflants sur votre écran.

WebGL - Graphics Pipeline

JavaScript : Le point de départ

Avant de plonger dans les profondeurs de WebGL, penchons-nous sur quelque chose de familier - JavaScript. WebGL est accessible via JavaScript, ce qui en fait le point d'entrée parfait pour notre aventure.

Votre Premier Programme WebGL

Commençons par un exemple simple :

// Récupère l'élément canvas
const canvas = document.getElementById('myCanvas');

// Récupère le contexte WebGL
const gl = canvas.getContext('webgl');

// Définit la couleur d'effacement (couleur de fond)
gl.clearColor(0.0, 0.0, 0.0, 1.0);

// Efface le canvas
gl.clear(gl.COLOR_BUFFER_BIT);

Dans ce morceau de code, nous faisons plusieurs choses :

  1. Nous obtenons une référence à notre élément canvas HTML.
  2. Nous obtenons le contexte de rendu WebGL.
  3. Nous définissons la couleur d'effacement (en l'occurrence, noir).
  4. Nous effaçons le canvas avec notre couleur spécifiée.

Cela peut ne pas sembler grand-chose, mais félicitations ! Vous venez de créer votre premier programme WebGL. C'est comme préparer une toile vierge pour une œuvre mestration.

Shader de sommet : Sculpter Votre Monde

Maintenant que nous avons notre toile prête, parlons des shaders de sommet. Pensez aux shaders de sommet comme aux sculpteurs de votre monde 3D. Ils travaillent avec les données brutes de vos objets - les sommets.

Un Shader de Sommet Simple

Voici un exemple de shader de sommet de base :

attribute vec4 a_position;

void main() {
gl_Position = a_position;
}

Ce shader fait quelque chose de simple mais crucial - il prend la position de chaque sommet et l'assigne à gl_Position. C'est comme dire à chaque point de votre objet 3D, "Tu vas ici !"

Assemblage des primitives : Connecter les points

Après que le shader de sommet a fait son travail, WebGL passe à l'assemblage des primitives. Cette étape est comme un jeu de connecter les points - elle prend les sommets individuels et détermine comment ils devraient être connectés pour former des formes.

Par exemple, si vous dessinez un triangle, l'assemblage des primitives prendrait trois sommets et comprendrait qu'ils forment un triangle unique.

Rasterisation : Pixels Partout

Maintenant, arrive la magie de la rasterisation. Cette étape transforme nos formes 3D en pixels 2D que vous voyez sur votre écran. C'est comme prendre une sculpture 3D et créer une photographie détaillée d'elle.

Shader de fragment : Colorier Votre Monde

Le shader de fragment est où se passe la véritable artistique. Alors que le shader de sommet s'occupe de la structure de vos objets, le shader de fragment les colore.

Un Shader de Fragment Simple

Voici un shader de fragment de base qui colore tout en rouge :

precision mediump float;

void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

Ce shader definit gl_FragColor à un vecteur représentant la couleur rouge (rouge complet, pas de vert, pas de bleu, opacité complète). C'est comme tremper tout votre monde 3D dans de la peinture rouge !

Opérations de fragment : Les touches finales

Après le shader de fragment, WebGL effectue diverses opérations sur les fragments. Cela inclut le test de profondeur (déterminer quelles objets sont devant les autres), le mélange (comment les objets transparents interagissent), et plus encore.

Buffer de trame : Le grand final

Enfin, nous atteignons le buffer de trame. C'est où votre image rendue est stockée avant d'être affichée sur l'écran. C'est comme une zone de幕后 où les dernières touches sont appliquées avant que le rideau se lève.

Mettre tout ensemble

Maintenant que nous avons parcouru chaque étape, voyons comment elles toutes travaillent ensemble dans un programme WebGL complet :

// Source du shader de sommet
const vsSource = `
attribute vec4 aVertexPosition;

void main() {
gl_Position = aVertexPosition;
}
`;

// Source du shader de fragment
const fsSource = `
precision mediump float;

void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;

// Initialiser les shaders
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vsSource);
gl.compileShader(vertexShader);

const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fsSource);
gl.compileShader(fragmentShader);

// Créer le programme de shaders
const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);

// Utiliser le programme
gl.useProgram(shaderProgram);

// Créer un buffer et envoyer les données
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
const positions = [
1.0,  1.0,
-1.0,  1.0,
1.0, -1.0,
-1.0, -1.0,
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

// Dire à WebGL comment extraire les positions du buffer de position dans l'attribut vertexPosition
const numComponents = 2;
const type = gl.FLOAT;
const normalize = false;
const stride = 0;
const offset = 0;
gl.vertexAttribPointer(
gl.getAttribLocation(shaderProgram, 'aVertexPosition'),
numComponents,
type,
normalize,
stride,
offset);
gl.enableVertexAttribArray(gl.getAttribLocation(shaderProgram, 'aVertexPosition'));

// Dessiner la scène
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);

Ce programme crée un carré rouge sur un fond noir. Voici un résumé :

  1. Nous définissons nos shaders de sommet et de fragment.
  2. Nous compilons ces shaders et les lions en un programme.
  3. Nous créons un buffer avec les positions des sommets de notre carré.
  4. Nous disons à WebGL comment interpréter ces données de buffer.
  5. Enfin, nous effaçons l'écran et dessinons notre carré.

Chaque étape correspond à une étape du pipeline de rendu graphique que nous avons discuté. C'est comme regarder une chaîne de production, où les matières premières (données de sommet) sont transformées en produit fini (pixels sur votre écran).

Tableau des méthodes

Voici un tableau des méthodes WebGL clés que nous avons utilisées :

Méthode Description
gl.createShader() Crée un objet shader
gl.shaderSource() Définit le code source d'un shader
gl.compileShader() Compile un shader
gl.createProgram() Crée un objet programme
gl.attachShader() Attache un shader à un programme
gl.linkProgram() Lie un objet programme
gl.useProgram() Définit le programme spécifié comme faisant partie de l'état de rendu actuel
gl.createBuffer() Crée un objet buffer
gl.bindBuffer() lie un objet buffer à une cible
gl.bufferData() Crée et Initialise le magasin de données d'un objet buffer
gl.vertexAttribPointer() Spécifie la disposition des données de sommet
gl.enableVertexAttribArray() Active un tableau d'attributs de sommet
gl.clearColor() Spécifie la couleur à utiliser lors de l'effacement des buffers de couleur
gl.clear() Efface les buffers à des valeurs prédéfinies
gl.drawArrays() Rend des primitives à partir de données de tableau

Et voilà ! Nous avons parcouru le pipeline de rendu graphique WebGL, de JavaScript jusqu'au buffer de trame final. Souvenez-vous, comme toute compétence, maîtriser WebGL prend de la pratique. Mais avec chaque ligne de code que vous écrivez, vous êtes un pas plus près de créer des graphiques 3D incroyables dans votre navigateur. Continuez à expérimenter, continuez à apprendre, et surtout, amusez-vous !

Credits: Image by storyset