Fragment Shader est un étage programmable du pipeline graphique qui détermine la couleur finale de chaque fragment (pixel) d'une image. Selon Khronos Group, 2025, le shader de fragments reçoit des données interpolées du Vertex Shader et effectue des calculs d'éclairage, de texturage et d'effets de couleur. Fragment Shader est invoqué pour chaque pixel, ce qui en fait l'étage le plus gourmand en ressources du pipeline graphique.
Points clés
Fragment Shader (shader de fragments ou de pixels) est un étage programmable du pipeline graphique qui calcule la couleur finale de chaque fragment de l'image. Un fragment est un pixel potentiel qui devient un pixel visible à l'écran après avoir passé les tests de profondeur et de stencil.
Fragment Shader s'exécute après la rastérisation, lorsque les primitives 3D (triangles) ont déjà été converties en un ensemble de fragments. Le shader reçoit des attributs interpolés — coordonnées de texture, normales, couleurs qui ont été calculées dans le Vertex Shader pour les sommets du triangle et interpolées linéairement pour chaque pixel à l'intérieur du triangle.
Avant l'avènement des shaders programmables (avant DirectX 8 / OpenGL 2.0), le calcul de la couleur des pixels était effectué par un pipeline fixe avec un ensemble limité d'opérations. Le Fragment Shader programmable est apparu en 2001 et a radicalement élargi les capacités graphiques : les développeurs ont obtenu un contrôle total sur la couleur de chaque pixel, permettant d'implémenter un éclairage photoréaliste, des matériaux complexes et des post-effets.
Fragment Shader est lancé par le GPU pour chaque fragment généré par le rastériseur. Chaque invocation de shader traite un fragment, lit ses données d'entrée, exécute le code utilisateur et écrit la valeur de sortie — la couleur du fragment au format RGBA.
Les données d'entrée de Fragment Shader incluent des attributs interpolés du Vertex Shader (coordonnées de texture, normales, couleurs), des variables uniform (sources de lumière, matrices) et des échantillonneurs de texture. Les données de sortie sont le vecteur de couleur (gl_FragColor dans OpenGL ES 2.0 ou une variable définie par l'utilisateur dans ES 3.0), qui est écrit dans le tampon de couleur.
#version 300 es
precision mediump float;
in vec2 vTexCoord;
uniform sampler2D uTexture;
out vec4 fragColor;
void main() {
fragColor = texture(uTexture, vTexCoord);
}
Fragment Shader est responsable de la qualité visuelle de l'image. Tous les effets que l'utilisateur voit à l'écran — couleur, ombres, reflets, transparence — sont calculés à cet étage du pipeline graphique.
L'opération la plus fréquente est l'échantillonnage de la couleur d'une texture à l'aide de coordonnées UV interpolées. Sampler2D et la fonction texture() permettent d'obtenir la couleur d'un pixel à partir d'un atlas de textures. Le filtrage (bilinéaire, trilinéaire, anisotropique) est contrôlé via les paramètres de l'échantillonneur et affecte la netteté de l'image à différents angles de vue.
Le modèle d'éclairage Phong est calculé dans Fragment Shader par pixel, ce qui donne des reflets plus lisses que l'éclairage par sommet (ombrage Gouraud). L'éclairage Phong comprend trois composantes : ambiante, diffuse et spéculaire.
// Fragment shader with Phong lighting
in vec3 vNormal;
in vec3 vPosition;
uniform vec3 uLightDir;
uniform vec3 uLightColor;
void main() {
vec3 norm = normalize(vNormal);
float diff = max(dot(norm, uLightDir), 0.0);
fragColor = vec4(uLightColor * diff, 1.0);
}
Fragment Shader permet d'appliquer du post-traitement : correction des couleurs via des tables de correspondance (LUT), flou (blur), effet de lueur (bloom) et tonemapping pour le rendu HDR. Tous ces effets fonctionnent au niveau du pixel et s'exécutent en temps réel.
La performance de Fragment Shader est le principal facteur limitant les FPS dans les jeux mobiles modernes. Étant donné que le shader est invoqué pour chaque pixel, même une légère augmentation de la complexité du code peut entraîner une baisse notable du taux d'images.
Pour les GPU mobiles (Qualcomm Adreno, ARM Mali), il est recommandé d'utiliser la mediump precision pour les variables float, de combiner les échantillonnages de texture, d'appliquer des tests early-z pour éliminer les fragments invisibles avant l'exécution du shader.
| Méthode | Description | Gain |
|---|---|---|
| Mediump precision | Précision 16 bits au lieu de 32 bits | Jusqu'à 2x de vitesse |
| Early-Z | Test de profondeur avant le shader | Réduction des invocations |
| Texture atlasing | Une texture au lieu de plusieurs | Moins de changements |
Les deux types de shaders sont programmables par le développeur, mais ils travaillent à différents étages du pipeline et résolvent différentes tâches. Fragment Shader est nettement plus gourmand en ressources en raison du nombre d'invocations.
| Paramètre | Fragment Shader | Vertex Shader |
|---|---|---|
| Nombre d'invocations | Millions (résolution d'écran) | Milliers (nombre de sommets) |
| Données d'entrée | Attributs interpolés | Attributs de sommets |
| Fonction principale | Calcul de la couleur du fragment | Transformation de géométrie |
| Accès aux textures | Complet (plusieurs échantillonneurs) | Limité |
| Impact sur la performance | Élevé (dépend de la résolution) | Modéré (dépend de la géométrie) |
Fragment Shader peut être simple (échantillonnage de texture) ou complexe (éclairage multicouche). Considérons deux exemples pratiques : le texturage de base et un effet de dégradé utilisant le temps.
#version 300 es
precision mediump float;
in vec2 vTexCoord;
in vec3 vColor;
uniform sampler2D uDiffuseMap;
out vec4 fragColor;
void main() {
vec4 texColor = texture(uDiffuseMap, vTexCoord);
fragColor = texColor * vec4(vColor, 1.0);
}
#include <metal_stdlib>
using namespace metal;
struct FragmentIn {
float2 texCoord;
float3 normal;
};
fragment float4
fragmentMain(FragmentIn in [[stage_in]],
texture2d<float> tex [[texture(0)]]) {
constexpr sampler s(filter = linear);
float4 color = tex.sample(s, in.texCoord);
return color;
}
Questions fréquentes
Fragment Shader est un mini-programme sur le GPU qui détermine la couleur de chaque pixel à l'écran. Si Vertex Shader détermine la forme de l'objet, alors Fragment Shader détermine l'apparence de cet objet — texture, éclairage, couleur.
Fragment Shader est invoqué pour chaque pixel à l'écran. Sur un appareil avec une résolution de 2532x1170 (iPhone), cela représente presque 3 millions d'invocations par image. À 60 FPS, le shader s'exécute 180 millions de fois par seconde, nécessitant une puissance de calcul énorme.
Dans Fragment Shader, on implémente : texturage, éclairage (Phong, PBR), ombres, reflets, réfractions, bloom, profondeur de champ, correction des couleurs, filtres LUT et génération procédurale de textures.
Utilisez la mediump precision pour les float, réduisez le nombre d'échantillonnages de texture, appliquez l'early-z culling, combinez les opérations du shader et évitez les branchements conditionnels dans le shader.
C'est la même chose. Le terme Fragment Shader est utilisé dans OpenGL / Vulkan, tandis que Pixel Shader est utilisé dans la terminologie Direct3D (Microsoft). Fonctionnellement, ils sont identiques : tous deux calculent la couleur de chaque fragment/pixel.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi