Achille 746
ACHILLE746
ExpertisesProcessusRésultatsPortfolioTechnologiesBlogFAQ
Lancer un projet
Accueil›Blog›Web Immersif & WebGL›Shaders GLSL : les effets visuels avancés qui rendent le web immersif
✨WEB IMMERSIF & WEBGL

Shaders GLSL : les effets visuels avancés qui rendent le web immersif

7 JUILLET 2026•Par l'équipe Achille 746•9 min de lecture

Les shaders sont le cœur du rendu GPU. Ce sont des programmes qui s'exécutent en parallèle sur des milliers de cœurs graphiques, calculant la couleur de chaque fragment (pixel) d'une scène 3D. Comprendre GLSL — le langage des shaders WebGL — est la clé pour créer des effets visuels impossibles à obtenir avec les matériaux standard de Three.js : liquides animés, distorsions de l'espace, effets de plasma, particules réactives à l'audio, dégradés procéduraux infinis. Ce guide passe de la théorie à la pratique avec des fragments shaders réutilisables en production.

Vertex shader et fragment shader : deux étapes du pipeline

Le pipeline de rendu WebGL comporte deux étapes programmables. Le vertex shaders'exécute une fois par sommet (vertex) de la géométrie. Son rôle principal est de transformer les positions 3D en coordonnées 2D à l'écran via les matrices model-view-projection. Il peut aussi déformer la géométrie : vagues, ondulations, morphing. Le fragment shaders'exécute une fois par fragment (pixel potentiel) entre les sommets. Il calcule la couleur finale du pixel — c'est lui qui contient la logique visuelle : textures, éclairage, effets.

// Vertex shader minimal
varying vec2 vUv;

void main() {
  vUv = uv;  // passe les coordonnées UV au fragment shader
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
// Fragment shader : dégradé animé
uniform float uTime;
uniform vec3 uColorA;
uniform vec3 uColorB;
varying vec2 vUv;

void main() {
  float noise = sin(vUv.x * 10.0 + uTime) * 0.5 + 0.5;
  vec3 color = mix(uColorA, uColorB, noise);
  gl_FragColor = vec4(color, 1.0);
}

Les types GLSL essentiels

GLSL est un langage typé statiquement, proche du C, avec des types vectoriels et matriciels natifs qui sont au cœur de toute la logique de rendu.

  • float, int, bool : scalaires de base. GLSL ne convertit pas implicitement entre types — écrire 1 au lieu de 1.0 dans un contexte float est une erreur de compilation.
  • vec2, vec3, vec4 : vecteurs à 2, 3 ou 4 composantes. Les composantes sont accessibles via .x .y .z .w (position), .r .g .b .a (couleur) ou.s .t .p .q (texture), avec du swizzling :color.rgb, position.xy, vec.zyx.
  • mat2, mat3, mat4: matrices de transformation. La multiplication matricielle est l'opération centrale du vertex shader.
  • sampler2D, samplerCube : références à des textures. On les échantillonne avec texture2D(sampler, uv).
  • uniform, attribute, varying : qualificateurs de communication entre CPU/GPU et entre les deux stages du pipeline.

Uniforms : communiquer entre JavaScript et GLSL

Les uniformssont des variables passées depuis JavaScript au shader, identiques pour tous les sommets et fragments d'un draw call. C'est le mécanisme pour passer le temps écoulé, les couleurs de palette, les positions de la souris, les paramètres d'effets.

const material = new THREE.ShaderMaterial({
  vertexShader,
  fragmentShader,
  uniforms: {
    uTime:   { value: 0 },
    uColorA: { value: new THREE.Color('#C026D3') },
    uColorB: { value: new THREE.Color('#14B8A6') },
    uMouse:  { value: new THREE.Vector2(0, 0) },
  },
});

// Dans la boucle d'animation :
material.uniforms.uTime.value = clock.getElapsedTime();

Bruit procédural : la texture infinie

La fonction de bruit de Perlin et ses dérivés (simplex noise, value noise) sont les outils les plus utilisés en GLSL pour créer des textures et des animations organiques : nuages, flammes, terrain, liquides. GLSL ne dispose pas de générateur de bruit natif — il faut l'implémenter ou importer une implémentation standard. Le simplex noise 2D de Stefan Gustavson est la référence : 200 lignes de GLSL qui produisent un bruit continu, isotrope et sans artefacts.

// Fragment shader : effet de plasma avec simplex noise
uniform float uTime;

// snoise2D() importé depuis la lib simplex noise
void main() {
  vec2 uv = vUv * 3.0;
  float n1 = snoise2D(uv + uTime * 0.3);
  float n2 = snoise2D(uv * 2.0 - uTime * 0.5);
  float plasma = n1 * 0.5 + n2 * 0.5;

  vec3 col = mix(
    vec3(0.75, 0.1, 0.83),  // purple
    vec3(0.08, 0.72, 0.65), // teal
    smoothstep(0.0, 1.0, plasma)
  );

  gl_FragColor = vec4(col, 1.0);
}

Post-processing : effets après rendu

Le post-processing applique des effets sur la scène entière après le rendu initial, en traitant le framebuffer comme une texture 2D dans un shader de plein écran. Three.js expose cette architecture via EffectComposer et ses Pass.

  • UnrealBloomPass : bloom haute qualité (halos lumineux sur les zones claires). Paramètres clés : strength (intensité), radius (étalement), threshold (seuil de luminosité).
  • FilmPass : grain cinématographique et scanlines pour un rendu analogique.
  • GlitchPass: perturbations numériques aléatoires — l'effet distortion très utilisé dans les interfaces cyberpunk.
  • ShaderPass personnalisé : votre propre fragment shader appliqué en post-processing — aberration chromatique, vignette, depth of field manuel, effet de dessin au trait.
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass.js';

const composer = new EffectComposer(renderer);
composer.addPass(new RenderPass(scene, camera));
composer.addPass(new UnrealBloomPass(
  new THREE.Vector2(window.innerWidth, window.innerHeight),
  1.5,   // strength
  0.4,   // radius
  0.85   // threshold
));

// Remplacer renderer.render(scene, camera) par :
composer.render();

Performance des shaders : les pièges à éviter

Un shader mal optimisé peut faire chuter le framerate de 60 fps à 10 fps sans avertissement. Les règles de base : éviter les branches conditionnelles (if/else) dans les shaders — le GPU exécute les deux branches en parallèle et garde le résultat de la condition vraie, gaspillant la moitié du calcul. Préférer mix(), step()et smoothstep() qui sont des opérations branchless. Limiter les texture samples par fragment : chaque texture2D() est une lecture mémoire coûteuse. Regrouper les uniforms en structou en vecteurs pack pour réduire les transfers CPU/GPU. Pour les patterns d'optimisation avancés, voir notre guide sur les performances WebGL.

“Un bon shader est comme un poème : chaque ligne compte. La contrainte du GPU force à une précision qui rend le code à la fois efficace et élégant.”

Les shaders GLSL sont la frontière entre un site web ordinaire et une expérience immersive qui restera en mémoire. Ils demandent un apprentissage spécifique — mathématiques vectorielles, pensée parallèle, débogage sans print — mais ouvrent des possibilités visuelles inégalées. Notre équipe, basée en Corrèze et intervenant en Nouvelle-Aquitaine et au-delà, développe des effets visuels sur mesure pour des projets qui exigent l'excellence. Pour donner vie à votre vision créative avec des shaders sur mesure, parlons de votre projet.

Article précédentThree.js : créer des scènes 3D interactives dans le navigateurTous les articlesArticle suivantOptimiser les performances WebGL : draw calls, instancing, LOD et textures
Partager cet article :Twitter / XLinkedIn

Articles liés

🌐
WebAssembly avec Rust : performances natives dans le navigateur et au-delà
8 min de lecture
→
🌐
Three.js : créer des scènes 3D interactives dans le navigateur
10 min de lecture
→
⚡
Optimiser les performances WebGL : draw calls, instancing, LOD et textures
10 min de lecture
→

Vous cherchez des effets visuels uniques pour votre site ou application ?

Nous développons des shaders GLSL sur mesure pour des expériences visuelles mémorables — plasma, distorsions spatiales, effets procéduraux — adaptés à votre identité de marque.

Discuter de votre projet →