Skip to content

Principes fondamentaux de WebGL pour les développeurs de jeux

WebGL vous donne un accès direct au GPU dans le navigateur. C’est la base des jeux web en 3D, ainsi que des jeux 2D performants. Ce tutoriel couvre les notions essentielles.

1) Obtenir un contexte WebGL

js
const canvas = document.getElementById('game')
const gl = canvas.getContext('webgl2') || canvas.getContext('webgl')

if (!gl) {
  // Fallback or error message
  console.error('WebGL not supported')
}

Privilégiez webgl2 lorsqu’il est disponible : il est largement pris en charge et offre de meilleures fonctionnalités.

2) Le pipeline de rendu (simplifié)

  1. Le vertex shader s’exécute une fois par sommet. Il positionne votre géométrie.
  2. Le fragment shader s’exécute une fois par pixel. Il colore le résultat.
  3. Les tampons contiennent les données (positions, coordonnées UV, couleurs).
  4. Les textures sont des images échantillonnées par les shaders.

3) Une paire minimale de shaders

Vertex shader :

glsl
#version 300 es
in vec2 a_position;
void main() {
  gl_Position = vec4(a_position, 0.0, 1.0);
}

Fragment shader :

glsl
#version 300 es
precision mediump float;
out vec4 fragColor;
void main() {
  fragColor = vec4(1.0, 0.5, 0.2, 1.0); // orange
}

4) Compiler et lier les shaders

js
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(gl.getShaderInfoLog(shader))
    gl.deleteShader(shader)
    return null
  }
  return shader
}

function createProgram(gl, vs, fs) {
  const program = gl.createProgram()
  gl.attachShader(program, vs)
  gl.attachShader(program, fs)
  gl.linkProgram(program)
  if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
    console.error(gl.getProgramInfoLog(program))
    return null
  }
  return program
}

5) Créer des tampons

js
const positions = new Float32Array([
  -0.5, -0.5,
   0.5, -0.5,
   0.0,  0.5,
])

const buffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW)

6) Relier les tampons aux shaders

js
const positionLoc = gl.getAttribLocation(program, 'a_position')
gl.enableVertexAttribArray(positionLoc)
gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0)

7) La boucle de jeu

js
function render() {
  gl.viewport(0, 0, canvas.width, canvas.height)
  gl.clearColor(0, 0, 0, 1)
  gl.clear(gl.COLOR_BUFFER_BIT)

  gl.useProgram(program)
  gl.drawArrays(gl.TRIANGLES, 0, 3)

  requestAnimationFrame(render)
}
render()

8) Charger des textures

js
function loadTexture(gl, url) {
  const texture = gl.createTexture()
  gl.bindTexture(gl.TEXTURE_2D, texture)

  // Placeholder pixel until image loads
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
    new Uint8Array([255, 0, 255, 255]))

  const img = new Image()
  img.onload = () => {
    gl.bindTexture(gl.TEXTURE_2D, texture)
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img)
    gl.generateMipmap(gl.TEXTURE_2D)
  }
  img.src = url
  return texture
}

9) Pièges courants

  • Les textures dont les dimensions sont des puissances de deux ne sont pas strictement obligatoires dans WebGL 2, mais les mipmaps fonctionnent mieux avec elles.
  • Perte du contexte : gérez les événements webglcontextlost — les navigateurs mobiles libèrent les contextes lorsqu’ils manquent de mémoire.
  • Les textures en virgule flottante nécessitent de vérifier la présence d’extensions (EXT_color_buffer_float).

10) Quand utiliser une bibliothèque

WebGL brut est verbeux. Pour la plupart des jeux, envisagez :

  • Three.js — solution 3D complète
  • PixiJS — rendu 2D rapide
  • PlayCanvas — moteur de jeu avec éditeur

Utilisez WebGL brut lorsque vous avez besoin :

  • d’un contrôle maximal
  • d’un moteur de rendu personnalisé
  • de comprendre comment les choses fonctionnent réellement

Une remarque pour 2026 : WebGPU est désormais activé par défaut dans tous les principaux navigateurs (Chrome et Edge depuis la version 113, Firefox 141 sous Windows et 145 sous macOS, ainsi que Safari sur iOS 26, iPadOS 26 et macOS Tahoe 26). Les principes fondamentaux présentés ici restent valables, puisque des bibliothèques comme Three.js utilisent leur moteur de rendu WebGPU avec un repli automatique vers WebGL 2. WebGL 2 demeure donc la référence fiable. Si vous commencez aujourd’hui un nouveau moteur de rendu à partir de zéro, lisez le tutoriel WebGPU en parallèle de celui-ci avant de choisir définitivement une API.

À lire aussi

Ressources externes