WebGL - Couleurs : Un Guide Pour Débutants pour Ajouter de la Vie à Vos Graphiques 3D

Salut à toi, aspirant passionné de WebGL ! Je suis ravi de être ton guide sur ce voyage coloré à travers le monde de WebGL. En tant que quelqu'un qui enseigne la graphique informatique depuis plus d'une décennie, je peux te dire que rajouter des couleurs à tes scènes 3D, c'est comme donner de la vie à une photographie en noir et blanc. C'est magique, et aujourd'hui, nous allons déverrouiller cette magie ensemble !

WebGL - Colors

Comprendre les Couleurs dans WebGL

Avant de plonger dans les détails de l'application des couleurs, penchons-nous un instant pour comprendre ce que signifient les couleurs dans le contexte de WebGL. Dans ce domaine numérique, les couleurs sont représentées en utilisant le modèle RVB ( Rouge, Vert, Bleu). Chaque couleur est une combinaison de ces trois couleurs primaires, avec des valeurs variant de 0.0 à 1.0.

Par exemple :

  • Rouge : (1.0, 0.0, 0.0)
  • Vert : (0.0, 1.0, 0.0)
  • Bleu : (0.0, 0.0, 1.0)
  • Blanc : (1.0, 1.0, 1.0)
  • Noir : (0.0, 0.0, 0.0)

Imagine cela comme mélanger des peintures, mais avec de la lumière à la place des pigments. C'est un peu comme être un artiste numérique avec une palette infinie à tes doigts !

Appliquer des Couleurs dans WebGL

Maintenant que nous avons compris les bases, mettons les mains dans le cambouis (ou devrais-je dire, dans les couleurs?) pour appliquer des couleurs dans WebGL.

Étapes pour Appliquer des Couleurs

  1. Définir les attributs de couleur dans ton shadeur de sommet
  2. Transférer les données de couleur depuis ton code JavaScript
  3. Utiliser la couleur dans ton shadeur de fragment

Reprenons ces étapes avec quelques exemples de code.

Étape 1 : Définir les Attributs de Couleur dans le Shadeur de Sommet

Tout d'abord, nous devons informer notre shadeur de sommet que nous allons travailler avec des couleurs. Voici comment on fait :

attribute vec4 a_Position;
attribute vec4 a_Color;
varying vec4 v_Color;
void main() {
gl_Position = a_Position;
v_Color = a_Color;
}

Dans ce code, nous définissons un attribut a_Color pour recevoir les données de couleur, et une variable v_Color pour transmettre la couleur au shadeur de fragment. C'est comme setting up une pipeline de couleur de notre code JavaScript jusqu'à nos pixels !

Étape 2 : Transférer les Données de Couleur depuis JavaScript

Maintenant, nous devons envoyer les données de couleur de notre code JavaScript au shadeur. Voici un exemple de la manière dont nous pourrions le faire :

// Définir les sommets et les couleurs
var vertices = new Float32Array([
0.0, 0.5, 1.0, 0.0, 0.0,  // Sommet 1 : x, y, r, g, b
-0.5,-0.5, 0.0, 1.0, 0.0,  // Sommet 2 : x, y, r, g, b
0.5,-0.5, 0.0, 0.0, 1.0   // Sommet 3 : x, y, r, g, b
]);

// Créer un buffer et envoyer les données dedans
var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

// Dire à WebGL comment lire le buffer
var FSIZE = vertices.BYTES_PER_ELEMENT;
var a_Position = gl.getAttribLocation(program, 'a_Position');
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 5, 0);
gl.enableVertexAttribArray(a_Position);

var a_Color = gl.getAttribLocation(program, 'a_Color');
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 5, FSIZE * 2);
gl.enableVertexAttribArray(a_Color);

Ce code peut sembler intimidant au premier abord, mais breaking it down :

  1. Nous définissons nos sommets et couleurs dans un seul tableau. Chaque sommet a 5 valeurs : x, y, r, g, b.
  2. Nous créons un buffer et envoyons nos données dedans.
  3. Nous disons à WebGL comment lire ce buffer, à la fois pour la position (premières 2 valeurs) et la couleur (dernières 3 valeurs).

C'est comme packer une valise avec des vêtements et des produits de toilette, et puis dire à ton ami exactement comment la déballer !

Étape 3 : Utiliser la Couleur dans le Shadeur de Fragment

Enfin, nous utilisons la couleur dans notre shadeur de fragment :

precision mediump float;
varying vec4 v_Color;
void main() {
gl_FragColor = v_Color;
}

Ce shadeur simple prend la couleur que nous avons transmise du shadeur de sommet et l'applique à notre fragment (pixel). C'est la dernière étape de notre voyage coloré, où la couleur finit par briller à l'écran !

Exemple – Appliquer une Couleur

Mettons tout ensemble avec un exemple complet. Nous allons créer un triangle coloré en utilisant le code que nous avons discuté.

<!DOCTYPE html>
<html>
<head>
<title>Triangle Couleur WebGL</title>
</head>
<body>
<canvas id="glCanvas" width="640" height="480"></canvas>
<script>
// Programme du shadeur de sommet
const vsSource = `
attribute vec4 a_Position;
attribute vec4 a_Color;
varying vec4 v_Color;
void main() {
gl_Position = a_Position;
v_Color = a_Color;
}
`;

// Programme du shadeur de fragment
const fsSource = `
precision mediump float;
varying vec4 v_Color;
void main() {
gl_FragColor = v_Color;
}
`;

function main() {
const canvas = document.querySelector("#glCanvas");
const gl = canvas.getContext("webgl");

if (!gl) {
alert("Impossible d'initialiser WebGL. Votre navigateur ou machine peut ne pas le supporter.");
return;
}

// Initialiser un programme de shadeur
const shaderProgram = initShaderProgram(gl, vsSource, fsSource);

// Obtenir les emplacements des attributs
const programInfo = {
program: shaderProgram,
attribLocations: {
vertexPosition: gl.getAttribLocation(shaderProgram, 'a_Position'),
vertexColor: gl.getAttribLocation(shaderProgram, 'a_Color'),
},
};

// Créer le buffer
const buffers = initBuffers(gl);

// Dessiner la scène
drawScene(gl, programInfo, buffers);
}

function initBuffers(gl) {
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

const positions = [
0.0,  0.5,  1.0, 0.0, 0.0,
-0.5, -0.5,  0.0, 1.0, 0.0,
0.5, -0.5,  0.0, 0.0, 1.0,
];

gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

return {
position: positionBuffer,
};
}

function drawScene(gl, programInfo, buffers) {
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);

gl.useProgram(programInfo.program);

{
const numComponents = 2;  // extraire 2 valeurs par itération
const type = gl.FLOAT;    // les données dans le buffer sont des flottants 32 bits
const normalize = false;  // ne pas normaliser
const stride = 20;        // combien d'octets pour passer d'un ensemble de valeurs au suivant
const offset = 0;         // combien d'octets à l'intérieur du buffer pour commencer
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position);
gl.vertexAttribPointer(
programInfo.attribLocations.vertexPosition,
numComponents,
type,
normalize,
stride,
offset);
gl.enableVertexAttribArray(
programInfo.attribLocations.vertexPosition);
}

{
const numComponents = 3;
const type = gl.FLOAT;
const normalize = false;
const stride = 20;
const offset = 8;
gl.vertexAttribPointer(
programInfo.attribLocations.vertexColor,
numComponents,
type,
normalize,
stride,
offset);
gl.enableVertexAttribArray(
programInfo.attribLocations.vertexColor);
}

gl.drawArrays(gl.TRIANGLES, 0, 3);
}

function initShaderProgram(gl, vsSource, fsSource) {
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);

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

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

return shaderProgram;
}

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

if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert('Une erreur est survenue lors de la compilation des shadeurs : ' + gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}

return shader;
}

window.onload = main;
</script>
</body>
</html>

Lorsque vous exécutez ce code, vous verrez un triangle magnifique avec des vertices rouges, verts et bleus. C'est comme voir un arc-en-ciel prendre vie sur votre écran !

Conclusion

Et voilà, les amis ! Nous avons fait un voyage à travers le monde coloré de WebGL, de la compréhension de la représentation des couleurs à leur application dans nos graphiques 3D. Souviens-toi, c'est juste le début. Avec ces bases sous le coude, tu es bien sur la voie de créer des graphiques 3D éblouissants et vibrants.

Alors, je suis rappelé d'un étudiant qui m'a dit un jour queapprendre les couleurs WebGL était comme peindre avec la lumière. Et tu sais quoi ? Il avait complètement raison. Alors, va donc, mes chers étudiants, et peins tes toiles numériques avec toutes les couleurs du vent (oui, c'est une référence Disney, et non, je ne suis pas honteux de l'admettre) !

Bonne programmation, et puissent tes aventures WebGL être toujours colorées !

Credits: Image by storyset