WebGL - Dessiner un Triangle

Salut à toi, futurs magiciens de WebGL ! Aujourd'hui, nous allons entreprendre un voyage passionnant dans le monde de la graphique informatique. Nous allons apprendre à dessiner un triangle en utilisant WebGL, ce qui pourrait sembler simple, mais croyez-moi, c'est la base de tous les graphiques 3D incroyables que vous voyez dans les jeux et les films. Alors, attachez vos ceintures et plongeons dedans !

WebGL - Drawing a Triangle

Qu'est-ce que WebGL ?

Avant de commencer à dessiner des triangles, penchons-nous sur ce qu'est WebGL. WebGL (Web Graphics Library) est une API JavaScript qui nous permet de rendre des graphiques 2D et 3D dans les navigateurs web sans utiliser de plugins. C'est comme avoir un superpouvoir qui vous permet de créer des visuels époustouflants directement dans votre navigateur web !

Étapes nécessaires pour dessiner un triangle

Dessiner un triangle dans WebGL pourrait sembler une tâche décourageante au départ, mais ne vous inquiétez pas ! Nous allons le décomposer en étapes gérables. Voici ce que nous devons faire :

  1. Configurer le canevas HTML
  2. Obtenir le contexte WebGL
  3. Créer et compiler le shader de sommet
  4. Créer et compiler le shader de fragment
  5. Créer un programme de shader
  6. Définir les sommets du triangle
  7. Créer un tampon et charger les données des sommets
  8. Lier les attributs des sommets
  9. Dessiner le triangle

Maintenant, passons à chaque étape en détail.

1. Configurer le canevas HTML

Tout d'abord, nous devons créer un canevas dans notre fichier HTML où WebGL rendra notre triangle. Voici comment nous faisons :

<canvas id="glCanvas" width="640" height="480"></canvas>

Cela crée un canevas avec un ID de "glCanvas" et des dimensions de 640x480 pixels. Vous pouvez ajuster ces dimensions selon vos besoins.

2. Obtenir le contexte WebGL

Passons maintenant à JavaScript. Nous devons obtenir le contexte WebGL de notre canevas :

const canvas = document.getElementById('glCanvas');
const gl = canvas.getContext('webgl');

if (!gl) {
console.error('Impossible d\'initialiser WebGL. Votre navigateur pourrait ne pas le supporter.');
return;
}

Ce code trouve notre canevas, demande le contexte WebGL, et vérifie si WebGL est pris en charge dans le navigateur.

3. Créer et compiler le shader de sommet

Un shader de sommet est un programme qui traite les données des sommets. Voici comment nous en créons un :

const vsSource = `
attribute vec4 aVertexPosition;
void main() {
gl_Position = aVertexPosition;
}
`;

function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);

if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error('Une erreur s\'est produite lors de la compilation des shaders : ' + gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}

return shader;
}

const vertexShader = createShader(gl, gl.VERTEX_SHADER, vsSource);

Ce code définit notre source de shader de sommet et une fonction pour créer et compiler des shaders.

4. Créer et compiler le shader de fragment

Un shader de fragment détermine la couleur de chaque pixel. Voici comment nous en créons un :

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

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

Ce shader de fragment colorera notre triangle en rouge.

5. Créer un programme de shader

Maintenant, nous devons lier nos shaders dans un programme :

const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);

if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
console.error('Impossible d\'initialiser le programme de shader : ' + gl.getProgramInfoLog(shaderProgram));
return;
}

6. Définir les sommets du triangle

Définissons les sommets de notre triangle :

const vertices = [
0.0,  0.5,  0.0,
-0.5, -0.5,  0.0,
0.5, -0.5,  0.0
];

Ces coordonnées définissent un triangle dans l'espace de clips, où chaque coordonnée varie de -1 à 1.

7. Créer un tampon et charger les données des sommets

Maintenant, nous devons créer un tampon et charger nos données des sommets dedans :

const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

8. Lier les attributs des sommets

Nous devons dire à WebGL comment interpréter nos données des sommets :

const aVertexPosition = gl.getAttribLocation(shaderProgram, 'aVertexPosition');
gl.vertexAttribPointer(aVertexPosition, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(aVertexPosition);

9. Dessiner le triangle

Enfin, nous pouvons dessiner notre triangle :

gl.useProgram(shaderProgram);
gl.drawArrays(gl.TRIANGLES, 0, 3);

Mettre tout ensemble

Voici notre code complet pour dessiner un triangle :

// Obtenir le contexte WebGL
const canvas = document.getElementById('glCanvas');
const gl = canvas.getContext('webgl');

if (!gl) {
console.error('Impossible d\'initialiser WebGL. Votre navigateur pourrait ne pas le supporter.');
return;
}

// Source du shader de sommet
const vsSource = `
attribute vec4 aVertexPosition;
void main() {
gl_Position = aVertexPosition;
}
`;

// Source du shader de fragment
const fsSource = `
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;

// Fonction pour créer un shader
function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);

if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error('Une erreur s\'est produite lors de la compilation des shaders : ' + gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}

return shader;
}

// Créer les shaders
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vsSource);
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fsSource);

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

if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
console.error('Impossible d\'initialiser le programme de shader : ' + gl.getProgramInfoLog(shaderProgram));
return;
}

// Définir les sommets
const vertices = [
0.0,  0.5,  0.0,
-0.5, -0.5,  0.0,
0.5, -0.5,  0.0
];

// Créer un tampon et charger les données des sommets
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

// Lier les attributs des sommets
const aVertexPosition = gl.getAttribLocation(shaderProgram, 'aVertexPosition');
gl.vertexAttribPointer(aVertexPosition, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(aVertexPosition);

// Dessiner le triangle
gl.useProgram(shaderProgram);
gl.drawArrays(gl.TRIANGLES, 0, 3);

Et voilà ! Vous avez dessiné votre premier triangle en utilisant WebGL. Cela pourrait sembler beaucoup d'étapes pour un simple triangle, mais souvenez-vous, c'est la base pour créer des graphiques 3D complexes. Chaque étape que nous avons passée est essentielle pour un rendu plus avancé.

Conclusion

Félicitations pour avoir dessiné votre premier triangle WebGL ! Vous avez fait votre premier pas dans le monde passionnant de la programmation graphique informatique. Souvenez-vous, chaque voyage commence par un seul pas - ou dans notre cas, un seul triangle. Continuez à pratiquer, continuez à explorer, et avant de savoir, vous créerez des graphiques 3D époustouflants qui feront flipper les gens !

Voici un tableau résumant les principales méthodes WebGL que nous avons utilisées :

Méthode Description
getContext('webgl') Obtient le contexte de rendu WebGL
createShader() Crée un objet shader
shaderSource() Définit le code source d'un shader
compileShader() Compile un shader
createProgram() Crée un objet programme
attachShader() Attache un shader à un programme
linkProgram() Lie un objet programme
createBuffer() Crée un objet tampon
bindBuffer() Lie un objet tampon à un target
bufferData() Crée et initialise le magasin de données d'un objet tampon
getAttribLocation() Retourne l'emplacement d'une variable d'attribut
vertexAttribPointer() Spécifie le layout des attributs des sommets
enableVertexAttribArray() Active un tableau d'attributs de sommets
useProgram() Définit le programme spécifié comme faisant partie de l'état de rendu actuel
drawArrays() Rend des primitives à partir de données de tableau

Gardez ce tableau à portée de main pendant que vous continuez votre voyage WebGL. Bon codage, et que vos triangles soient toujours parfaitement rendus !

Credits: Image by storyset