Introduction
GLSL (OpenGL Shading Language) est le langage standard pour programmer les shaders dans WebGL, la bibliothèque JavaScript pour le rendu 3D dans les navigateurs. En 2026, malgré l'essor de WebGPU, GLSL reste essentiel pour 90% des projets WebGL existants et les performances critiques comme les jeux browser ou les visualisations de données. Ce tutoriel beginner vous emmène des bases aux premiers effets : un triangle rotatif multicolore. Imaginez un moteur de rendu comme une chaîne de montage – les vertex shaders transforment les positions (comme des ouvriers modelant des pièces), les fragment shaders colorent les pixels (comme des peintres finissant le produit). Vous obtiendrez un fichier HTML autonome, servable en local, avec 200 lignes de code total. À la fin, vous saurez compiler, linker et animer des shaders, prêt pour des effets avancés comme les textures ou le ray tracing basique. Pas de frameworks : pur WebGL pour comprendre les fondations.
Prérequis
- VS Code avec l'extension Live Server (pour servir les fichiers localement via HTTP).
- Connaissances basiques en HTML et JavaScript (variables, fonctions, async/await).
- Navigateur moderne (Chrome 120+ ou Firefox 130+ pour WebGL 1.0).
- Créez un dossier
glsl-debutantsur votre bureau.
Initialiser le projet
mkdir glsl-debutant
cd glsl-debutant
touch index.html vertex.glsl fragment.glsl script.js
code .Cette commande crée le dossier projet et les 4 fichiers essentiels. Ouvrez VS Code avec code . pour éditer. Live Server nécessitera HTTP pour fetch() des shaders ; sans ça, CORS bloque. Testez toujours en serveur local, pas file://.
Structure HTML de base
L'HTML fournit le canvas : une zone de rendu comme un écran TV vide. On lie le script JS pour l'initialisation WebGL. Cliquez droit sur index.html > Open with Live Server pour lancer à http://127.0.0.1:5500.
Fichier index.html
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Premier Shader GLSL</title>
<style>
body { margin: 0; background: #222; display: flex; justify-content: center; align-items: center; height: 100vh; }
canvas { border: 2px solid #fff; }
</style>
</head>
<body>
<canvas id="glCanvas" width="600" height="400"></canvas>
<script src="script.js"></script>
</body>
</html>Ce squelette HTML centre un canvas 600x400px sur fond noir. Le CSS assure un rendu plein écran responsive. Le script.js chargera WebGL : sans lui, le canvas reste vide. Dimensions fixes évitent les redimensionnements complexes pour débutants.
Le Vertex Shader : transformer les positions
Un vertex shader traite chaque sommet (coin du triangle) comme un ouvrier pliant du métal. Il applique une matrice de rotation via uniform (données globales du JS). attribute = données par sommet (position, couleur), varying = passe à fragment.
Vertex shader GLSL
attribute vec2 a_position;
attribute vec3 a_color;
varying vec3 v_color;
uniform mat3 u_matrix;
void main() {
// Multiplie position par matrice 3x3 pour rotation/scale
gl_Position = vec4((u_matrix * vec3(a_position, 1)).xy, 0, 1);
v_color = a_color;
}Ce shader prend 2D positions/colors, applique u_matrix pour rotation (comme tourner une pizza uniformément). gl_Position est obligatoire en -1..1 clip space. Pas de precision car WebGL1 infère ; évitez vec4 inutiles pour perf.
Le Fragment Shader : colorer les pixels
Le fragment shader s'exécute par pixel (fragment), comme un pinceau coloriant chaque point. Il reçoit v_color du vertex et l'applique. Simple pour début : pas de textures, juste interpolation.
Fragment shader GLSL
precision mediump float;
varying vec3 v_color;
void main() {
gl_FragColor = vec4(v_color, 1.0);
}precision mediump float assure compatibilité mobile (lowp=faible, highp=précis mais lent). gl_FragColor est legacy WebGL1 ; pour WebGL2, utilisez out vec4 outColor. Interpolation auto mélange couleurs entre sommets.
JavaScript : compiler et lier les shaders
Le JS orchestre : fetch shaders, compile (check erreurs), link en program, upload données (buffers), set uniforms, draw. Analogie : assembler une voiture (shaders=pièces, program=moteur).
Script JS initialisation
async function initWebGL() {
const canvas = document.getElementById('glCanvas');
const gl = canvas.getContext('webgl');
if (!gl) { alert('WebGL non supporté'); return; }
// Fetch et compile shaders
const vsSource = await (await fetch('vertex.glsl')).text();
const fsSource = await (await fetch('fragment.glsl')).text();
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vsSource);
gl.compileShader(vertexShader);
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
console.error('Vertex error:', gl.getShaderInfoLog(vertexShader));
return;
}
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fsSource);
gl.compileShader(fragmentShader);
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
console.error('Fragment error:', gl.getShaderInfoLog(fragmentShader));
return;
}
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error('Link error:', gl.getProgramInfoLog(program));
return;
}
gl.useProgram(program);
// Buffers positions (triangle)
const positions = new Float32Array([
0, -0.5,
-0.5, 0.5,
0.5, 0.5
]);
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
const positionLoc = gl.getAttribLocation(program, 'a_position');
gl.enableVertexAttribArray(positionLoc);
gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);
// Buffers couleurs
const colors = new Float32Array([
1, 0, 0, // Rouge
0, 1, 0, // Vert
0, 0, 1 // Bleu
]);
const colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
const colorLoc = gl.getAttribLocation(program, 'a_color');
gl.enableVertexAttribArray(colorLoc);
gl.vertexAttribPointer(colorLoc, 3, gl.FLOAT, false, 0, 0);
// Uniform matrix
const matrixLoc = gl.getUniformLocation(program, 'u_matrix');
// Render loop
function render(time) {
time *= 0.001;
// Matrice rotation 2D
const cos = Math.cos(time);
const sin = Math.sin(time);
const matrix = [
cos, -sin, 0,
sin, cos, 0,
0, 0, 1
];
gl.uniformMatrix3fv(matrixLoc, false, matrix);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, 3);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
initWebGL();Ce script async fetch/compile/link shaders, upload buffers (positions triangle RGB), set uniform matrix rotative. requestAnimationFrame anime à 60fps. Logs erreurs en console : toujours check getShaderInfoLog pour debug syntaxe GLSL. Buffers STATIC_DRAW optimisés car statiques.
Test et rendu
Ouvrez Live Server : vous verrez un triangle RGB rotatif ! Inspectez console pour erreurs. Modifiez couleurs dans JS ou ajoutez time en varying pour effets temporels.
Bonnes pratiques
- Toujours logger erreurs :
getShaderInfoLogsauve des heures (syntaxe GLSL stricte, pas de warnings). - Utilisez matrices 3x3 pour 2D : plus efficaces que 4x4, évitez translations complexes au début.
- Precision qualifiers :
mediumppar défaut mobile ; testez highp sur desktop. - Buffers séparés : positions/colors pour réutilisabilité (ex: changer couleurs sans rebuffer positions).
- requestAnimationFrame : synchronise avec écran, évite gaspillage CPU.
Erreurs courantes à éviter
- CORS fetch : Ne pas servir en file:// ; Live Server obligatoire pour
fetch('vertex.glsl'). - gl_Position manquant : Shader compile mais rien ne rend ; toujours set en vec4(-1..1).
- Attribs non enabled : Oublier
enableVertexAttribArray= sommets ignorés, écran noir. - Uniform non trouvé : Typos comme
U_matrixau lieuu_matrixcrash link.
Pour aller plus loin
- Ajoutez textures :
sampler2Den fragment,texture2Dpour images. - Passez à WebGL2 :
#version 300 es,in/outau lieu attribute/varying. - Libs : three.js pour abstraire, mais revenez à pur WebGL pour perf.
- Ressources : Spec GLSL ES 1.00, WebGL Fundamentals.