Tutoriel 9 - Interpolation

Par OGLdev, traduit par DragonJoker

Récupérer les sources



Introduction

Etude de l'interpolation effectuée par le rasterizer sur les variables qui sortent du vertex shader.

Contexte

Ce tutoriel montre une partie très importante du pipeline 3D : l'interpolation effectuée par le rasterizer sur les variables qui sortent du vertex shader.

Comme vous l'avez déjà vu, afin d'obtenir quelque chose de significatif sur l'écran, vous devez utiliser une des variables de sortie du VS : « gl_Position ». Il s'agit d'un vecteur 4 qui contient les coordonnées homgènes du sommet.

Les composantes XYZ de ce vecteur sont divisées par la composante W (procédé connu sous le nom de « perspective divide » et dont nous traitons dans le tutoriel dédié à ce sujet) et toutes les composantes qui sortent de la boîte normalisée ([-1,1] pour XY; [0,1] pour Z) sont découpées.

Le résultat est transformé dans le système de coordonnées écran et ensuite le triangle (ou tout autre type de primitive supporté) est rendu à l'écran par le rasterizer.

Le rasterizer effectue une interpolation entre les trois sommets du triangle (soit de ligne en ligne ou par une autre technique) et « visite » chaque pixel dans le triangle en exécutant le fragment shader.

Le fragment shader doit renvoyer une couleur de pixel que le rasterizer place dans le tampon de couleur pour l'affichage (après plusieurs étapes additionnelles telles que le test de profondeur, etc).

N'importe quelle autre variable sortant du vertex shader ne passe pas par les étapes décrites ci-dessus.

Si le fragment shader ne requiert pas explicitement une variable (et vous pouvez mixer et associer plusieurs fragment shaders avec le même vertex shader) alors une optimisation commune sera de supprimer toutes les instructions dans le VS qui n'affectent que cette variable (pour ce programme spécifique qui combine cette paire de VS et FS).

Cependant si le FS utilise cette variable, le rasterizer l'interpole durant la rasterization et fournit à chaque invocation du FS la valeur interpolée qui correspond à cet emplacement spécifique.

Cela signifie généralement que les valeurs pour les pixels qui sont proches les uns des autres seront un peu différentes (même si, le triangle s'éloignant de plus en plus de la caméra, cela devient moins probable).

Deux variables très communes se basent sur l'interpolation : la normale du triangle et les coordonnées de texture.

La normale d'un sommet est habituellement calculée comme la moyenne des normales de tous les triangles qui contiennent ce sommet. Si cet objet n'est pas complètement plat, cela signifie habituellement que les normales des trois sommets de chaque triangle seront différentes les unes des autres

Dans ce cas nous nous fions à l'interpolation pour calculer la normale à chaque pixel. Cette normale est utilisée dans les calculs d'éclairage afin de générer une représentation plus crédible des effets de lumières.

Le cas des coordonnées de texture est similaire. Ces coordonnées font partie du modèle et sont spécifiées par sommet. Afin de couvrir le triangle avec une texture, vous devez effectuer l'opération d'échantillonage pour chaque pixel et spécifier les coordonnées de texture correctes pour ce pixel. Ces coordonnées sont le résultat de l'interpolation.

Dans ce tutoriel nous allons voir les effets de l'interpolation en interpolant différentes couleurs au travers de la face triangulaire.

Comme je suis fainéant, nous allons générer la couleur dans le VS.

Une approche plus fastidieuse serait de la fournir dans le tampon de sommets. Généralement vous ne fournirez pas de couleurs à partir du tampon de sommets.

Vous fournissez des coordonnées de texture et échantillonnez la couleur à partir de la texture.

Cette couleur sera ensuite utilisée par les calcul d'éclairage.

Explication du code

Les paramètres passés entre les étapes du pipeline doivent être déclarées en utilisant le mot clé « out » dans le contexte global du shader.

La couleur est un vecteur 4 car les composantes XYZ contiennent les composantes RGB (respectivement) et la composante W correspond à la valeur d'alpha (transparence du pixel).

Color = vec4(clamp(Position, 0.0, 1.0), 1.0);

La couleur dans les pipelines graphiques est généralement représentée en utilisant des valeurs en nombres flottants dans l'ensemble [0.0, 1.0].

Cette valeur est ensuite mise en correspondance avec un entier entre 0 et 255 pour chaque canal de la couleur (pour un total de 16M de couleurs).

Nous définissons la couleur du sommet comme fonction de sa position. Tout d'abord nous utilisons la fonction intégrée clamp() afin d'être sûr que les valeurs ne sortent pas des bornes [0.0, 1.0].

La raison est que le sommet en bas à gauche du triangle est positionné en (-1, -1). Si nous prenons cette valeur telle quelle, elle sera interpolée par le rasterizer et jusqu'à ce que X et Y dépassent zéro nous ne verrons rien car chaque valeur inférieure ou égale à zéro sera rendue en noir.

Cela signifie que la moitié du bord dans chaque direction sera noire avant que la couleur dépasse zéro et devienne significative. En fixant la valeur, nous faisons en sorte que seule la partie en bas à gauche soit noire, mais comme nous nous en éloignons rapidement, la couleur devient rapidement plus claire.

Essayez de jouer avec la fonction clamp(), en l'enlevant ou en modifiant ses paramètres, pour en voir l'effet.

Le résultat de la fonction clamp() ne va pas directement dans la variable de sortie car c'est un vecteur 4 alors que la position est un vecteur 3 (clamp() ne change pas le nombre de composantes, seulement leur valeur).

Du point de vue de GLSL il n'y a pas de conversion par défaut pour cela et nous devons donc le faire explicitement.

Nous le faisons en utilisant la notation « vec4( vec3, W ) » qui crée un vecteur 4 en concaténant un vecteur 3 avec la valeur W fournie. Dans notre cas nous utilisons 1.0 car elle va dans la composante alpha de la couleur et nous voulons que le pixel soit complètement opaque.

in vec4 Color;

La partie opposée de la couleur sortie du VS est la couleur en entrée du VS. Cette variable subit l'interpolation par le rasterizer afin que chaque FS soit (probablement) exécuté avec une couleur différente.

FragColor = Color;

Nous utilisons la couleur interpolée comme couleur du fragment sans autre chagement et cela termine ce tutoriel.

Remerciements

Merci à Etay Meiri de me permettre de traduire ses tutoriels.

Résultat :
resultat

Article d'origine