Qu'est ce qu'un shader

Un shader est un programme défini pour l'utilisateur qui est exécuté sur la carte graphique (et donc en parallèle). Les shaders ont été introduits pour permettre au développeur d'adapter la manière dont le rendu des données est réalisé (/adaptation du Pipe-Line Graphique). En particulier, les shaders permettent de modifier l'apparence des matériaux (apparence visuelle de la "matière" des objets virtuels) en fonction de l'orientation de la lumière - appelé shading. Le nom de shader est resté, bien qu'ils puissent aujourd'hui être utilisés au-delà de l'action de la lumière sur la forme (ex. déformation géométrique, subdivision, calculs génériques, etc).

Les shaders OpenGL sont écrits en langage GLSL (OpenGL Shading Language). Le GLSL ressemble à du code C++ simplifié, et spécialisé pour la manipulation de données 3D à l'aide de vecteurs et matrices.

Pour être exécuté par la carte graphique, le code GLSL doit être compilé et lié en un shader program binaire. A l'opposé de la compilation d'un code C++, la compilation des shader est très rapide, celle-ci est réalisée à chaque lancement du programme exécutable (compilation dite jit: just in time).

Un shader program est composé (d'au moins) deux parties différentes: Le vertex shader et le fragment shader
  • Note: Il est aussi possible de rencontrer Geometry, Tessellation et Compute shaders.

Vertex shaders correspond à un programme exécuté en parallèle sur chaque sommet (vertex) des données. Le rôle typique du vertex shader consiste à appliquer la matrice de projection sur chacun des sommets du maillage. Plus généralement un vertex shader reçoit en entrée des sommets, et renvoie des informations de sommets modifiés.
Le sommet en sortie du vertex shader se place dans un espace de vue cubique normalisé entre \([-1,1]\) appelé clip coordinates. Seul les sommets dont les coordonnées sont dans ce cube seront visible à l'écran.

Fragment shaders correspond à un programme exécuté en parallèle sur chaque fragment visible dans la fenêtre. Un fragment correspond à un élément de primitive rasterisé (\(\simeq\) un pixel appartenant à un morceau visible d'un triangle). Le rôle typique du fragment shader consiste à calculer la couleur finale d'un fragment (et donc d'un pixel affiché). Plus généralement, un fragment shader reçoit en entrée des données de sommets interpolées linéairement sur la primitive, et renvoie en sortie une couleur.

L'étape de "rasterization" est réalisée automatiquement au niveau de la carte graphique, et a lieu après que le vertex shader, et le fragment shader.