IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Les shaders dans OpenGL

Introduction à la programmation de shaders GLSL

Les shaders dans OpenGL

Introduction à la programmation de shaders GLSL


précédentsommairesuivant

4. Étude des shaders

4-A. Techniques de base

4-A-1. Éclairage

Exemple d'éclairage Exemple d'éclairage

L'éclairage est une partie importante pour toute application graphique. Nous allons reproduire le comportement du pipeline fixe lors du calcul des lumières.

Pour rappel, nous distinguons trois types de sources :

  • La lampe directionnelle ;
  • Le spot ou projecteur (voyons le comme un cône ayant sa pointe à la source de la lampe) ;
  • Le point de lumière (point light) (pensez à une luciole).


Lors du calcul de l'éclairage, nous distinguons trois types de lumière :

  • la lumière ambiante représentant une lumière globale ;
    Lumière ambiante
  • la lumière diffuse représentant les rayons rebondissant sur nos objets des différentes sources de lumière ;
    Lumière diffuse
  • la lumière spéculaire représentant le reflet des lumières.
    Lumière réfléchissante


Avant de commencer les calculs, il faut déterminer les besoins afin de décrire les lumières. Les informations à passer à notre shader sont les suivantes :

  • la position de la lumière. Effectivement, avec la position de la lumière, il sera plus facile de calculer la zone éclairé par la lumière ;
  • la couleur ambiante de la lumière ;
  • la couleur diffuse de la lumière ;
  • la couleur spéculaire de la lumière.


Seulement pour les spots et les points de lumière :

  • atténuation constante ;
  • atténuation linéaire ;
  • atténuation quadratique.


Seulement pour les spots :

  • une direction ;
  • un angle d'ouverture.
  • un coefficient d'exposition (un objet en plein dans l'angle du spot sera plus éclairé qu'un objet à la limite de la zone éclairée par le spot) ;
  • une limite d'éclairage (pour définir là ou le spot n'éclaire plus, car l'objet est trop loin).

Il est toujours possible de ne pas utiliser toutes ces informations afin de simplifier et/ou d'optimiser les calculs.

Pour les exemples de code qui suivent, nous allons partir du principe que nous utilisons la structure suivante :

Structure des informations pour la lumière
Sélectionnez
struct Lumiere
{
    vec3 position;
    vec4 couleurAmbiante;
    vec4 couleurDiffuse;
    vec4 couleurSpeculaire;
    float shininess ; // Seulement pour la lumière spéculaire
// Spécifique aux spots et points
    float attenuationConstante ;
    float attenuationLineaire ;
    float attenuationQuadratique ;
// Spécifique aux spots
    vec3 direction ;
    float angle ;
    float exposition;
    float limite;
}

Afin de faire les calculs de lumière diffuse et de lumière spéculaire, nous avons besoin des normales pour chaque vertex de nos objets. Finalement, il est nécessaire de connaître l'inverse de la matrice de vue, pour le calcul de la lumière spéculaire.

4-A-1-A. La lumière ambiante

Certainement la plus simple à appliquer, celle-ci est simplement une application de la couleur ambiante sur l'objet à éclairer.

Calcul de la lumière ambiante
Sélectionnez
couleurAmbiante = lumiere.ambiant;

4-A-1-B. La lumière diffuse

Schématisation de la lumière diffuse
Schématisation de la lumière diffuse

La lumière diffuse est une application de la formule de la réflexion de Lambert :

  • intensité = couleur_de_la_lumière_diffuse * cos(angle_entre_le_rayon_de_la_lumière_et_la_normale_de_l'objet)


Comme vous pouvez le constater, la couleur que l'on applique sur le pixel n'est qu'une fraction de la lumière de la lampe. La fraction dépend de l'angle entre le rayon lancé par la lampe sur l'objet et de l'orientation de l'objet (sa normale).

Le rayon de la lumière n'est autre que le vecteur entre la lumière et le point d'impact de celle-ci. Il est simple de connaître ce vecteur car nous avons la position de la source de lumière mais aussi la position du point de rebond. Ce point est exactement celui dont nous calculons l'intensité de la lumière. L'opération sera donc :

Calcul du vecteur entre le vertex et la lumière
Sélectionnez
Vec3 rayon = lumiere.position – vertex;

(Note : La position du la lumière doit être normalisée)

Pour connaître le cosinus de l'angle entre deux vecteurs nous allons utiliser le produit scalaire (en anglais : dot product). Le GLSL nous fournit une fonction appelé 'dot' pour appliquer ce calcul. Nous aurons donc dans notre code :

Calcul de l'angle entre le rayon de la lumière et la normale de l'objet
Sélectionnez
float angleLumiere = dot(normal, rayon);

Finalement, nous pouvons appliquer la formule de la réflexion de Lambert :

Calcul de la lumière diffuse
Sélectionnez
Vec3 couleurDiffuse = lumiere.diffuse * angleLumiere;

4-A-1-C. La lumière spéculaire

Schématisation de la lumière spéculaire
Schématisation de la lumière spéculaire

La lumière spéculaire est le reflet de la lampe sur l'objet que nous dessinons. Pour calculer celle-ci nous utilisons le modèle simplifié Blinn-Phong. La formule de ce modèle est la suivante :

  • spec = (Normale . (Oeil – rayon_lumière))shininess * couleur_de_la_lumière_speculaire


Pour connaître la position de l'œil, nous allons utiliser la position du vertex que nous sommes actuellement entrain de calculer pour lui appliquer la matrice inverse de vue. Pour rappel, la matrice de vue, permet de transformer des coordonnées de l'espace monde à l'espace de la caméra. La multiplication avec la matrice inverse fait donc l'opération inverse, ainsi, nous pouvons retrouver la position de la caméra. Le code de cette opération est le suivant :

Calcul de la position de la camera
Sélectionnez
Vec3 oeil = matrice_inverser_vue * vertex;

Le rayon_lumière, qui représente le vecteur entre la lumière et l'objet se calcule en soustrayant la position de la lumière à celle du vertex :

Calcul du vecteur de lumière
Sélectionnez
Vec3 ray = lumiere.position – vertex;

Le reste de la formule ne pose pas de problème. Pour rappel, afin d'effectuer les calculs sur les puissances le GLSL fournit la fonction pow (pour 'power' qui signifie puissance en anglais). La variable appelée 'shininess' correspond à la force du reflet.

Calcul de la lumière spéculaire
Sélectionnez
vec3 couleurSpeculaire = pow(dot(normale,(oeil-ray)),lumiere.shininess) * lumiere.couleurSpeculaire;

Voici les résultats avec un shininess de 8, 64 et 128 :
Spéculaire avec un shininess de 8Spéculaire avec un shininess de 64Spéculaire avec un shininess de 128

4-A-1-D. Application de nos différentes lumières

Le calcul final de la couleur se résume à la somme des différentes lumières. Toutefois, la lumière spéculaire ne doit pas apparaître si l'angle de la lumière (défini lors du calcul de la lumière diffuse) est inférieur à zéro (il serait dommage de voir le reflet de la lampe alors que celle-ci éclaire l'autre face de l'objet).

Calcul de la couleur finale
Sélectionnez
gl_FrontColor = couleurAmbiante + couleurDiffuse + couleurSpeculaire;
Résultat de l'éclairage
Résultat de l'éclairage

Maintenant que nous savons comment calculer les différentes lumières, nous allons découvrir comment reproduire les différents types de lampe. Les formules que nous avons apprises juste ci-dessus sont appliquées dans les trois cas, seulement des effets d'atténuation, ou de limite sont ajoutés.

4-A-1-E. Lampe directionnelle

Schématisation d'une lampe directionnelle
Schématisation d'une lampe directionnelle

La lampe directionnelle peut être comparée au soleil. Ainsi nous pouvons prétendre que la lumière est à une distance infinie, ce qui nous permet de considérer tout les rayons parallèles et ne subissant aucune atténuation. Pour l'appliquer, nous n'avons besoin que de la direction de ses rayons (ou de la position de la lampe). Cela nous simplifie énormément les calculs.

En fait, comme il s'agit d'une lampe sans atténuation, qui éclaire le monde entier, les calculs de la lumière peuvent être effectués tels qu'ils ont été présentés précédemment.

4-A-1-F. Point de lumière

Schématisation d'un point de lumière
Schématisation d'un point de lumière

Cette lampe ne se base que sur la distance des objets. Selon cette distance, l'objet sera plus ou moins éclairé. De plus, cette lampe éclaire dans toutes les directions.

Comme vous avez pu le deviner, il nous faut calculer la distance de la lampe à l'objet :

Calcul de la distance des objets
Sélectionnez
Vec3 vLumObj = lumiere.position – vertex ;
                  float distance = length(vLumObj);

Puis, encore une fois, nous allons calculer l'atténuation selon cette distance :

Calcul de l'atténuation selon la distance
Sélectionnez
float attenuation = lumiere.attenuationConstante  +
                  lumiere.attenuationLineaire * d +
                  lumiere.attenuationQuadratique * d * d;

Finalement, nous n'avons plus qu'à appliquer cette atténuation sur la lumière :

Calcul de la lumière selon l'atténuation du point de lumière
Sélectionnez
couleurAmbiante = couleurAmbiante * attenuation ;
                  couleurDiffuse = couleurDiffuse * attenuation ;
                  couleurSpeculaire = couleurSpeculaire * attenuation;

4-A-1-G. Spot

Schématisation d'un spot
Schématisation d'un spot

Le spot peut être représenté par un cône ayant la pointe à la source de la lampe. Si l'objet éclairé est au centre du cône, il reçoit la lumière « forte », mais si celui-ci est sur les bords, la couleur de la lumière est atténuée.

Déjà vous pouvez vous douter des besoins d'une telle lampe. Il nous faut :

  • la direction de la lumière;
  • l'angle d'ouverture du cône ;
  • atténuation constante ;
  • atténuation linéaire ;
  • atténuation quadratique ;
  • une limite d'éclairage ;
  • un coefficient d'exposition.


Commençons par récupérer la distance entre notre lampe et notre objet. Lors du calcul du rayon de la lumière, nous avons vu comment récupérer le vecteur entre la lumière et l'objet. Pour calculer la distance à partir d'un vecteur, le GLSL nous fournit une fonction toute prête : length() (qui signifie 'distance' en anglais).

Calcul de la distance entre la lumière et l'objet
Sélectionnez
Vec3 vLumObj = lumiere.position – vertex ;
float distance = length(vLumObj);

Maintenant, nous allons calculer l'atténuation selon la distance de l'objet. Pour cela, nous allons reprendre la formule utilisée par OpenGL dans son pipeline fixe.

Calcul de l'atténuation selon la distance
Sélectionnez
float attenuation = lumiere.attenuationConstante  +
lumiere.attenuationLineaire * d +
lumiere.attenuationQuadratique * d * d;

Ensuite nous devons savoir si l'objet est dans le cône de lumière de la lampe. Pour cela nous allons calculer l'angle entre le vecteur de la position de la lampe à l'objet et le vecteur entre l'objet et la direction de la lampe. Encore une fois, nous utilisons le produit scalaire :

Calcul de l'angle entre le l'objet et la lampe et l'objet de la direction de la lampe
Sélectionnez
float angle = dot(-vLumObj, normalize(lumiere.direction));

Nous allons calculer une deuxième atténuation qui, cette fois, dépend de l'angle entre le spot et l'objet.

Atténuation selon l'angle
Sélectionnez
float spotAttenuation = 0.0f
if ( angle >= lumiere.limite )
{
    spotAttenuation = pow(angle,lumiere.exposition);
}

Nous appliquons cette atténuation sur la première que nous avions trouvée :

Application de l'atténuation
Sélectionnez
attenuation *= spotAttenuation;

Pour finir, nous appliquons l'atténuation dans notre calcul de la lumière :

Calcul de la lumière selon l'atténuation du spot
Sélectionnez
couleurAmbiante = couleurAmbiante * attenuation ;
couleurDiffuse = couleurDiffuse * attenuation ;
couleurSpeculaire = couleurSpeculaire * attenuation;

4-A-1-H. Matériaux

Il nous reste une toute petite partie (optionnelle) lors du calcul de l'effet de lumière sur notre objet. Actuellement, dans nos calculs de lumière nous n'avons pas pris en compte la couleur de nos objets. Plus précisément, nous parlons de matériaux, car les objets peuvent réfléchir de différente manière la lumière.

Pour décrire un matériau il faut définir :

  • la couleur;
  • la couleur diffuse (celle qui est renvoyé à l'œil) ;
  • la couleur spéculaire (une altération du reflet de la lumière, par le matériau).


Pour appliquer un matériau, il faut juste suivre la formule suivante :

(Je pars du principe, que les différentes couleurs contiennent les valeurs précédentes de nos calculs de lumière). La structure pour les matériaux peut être la suivante :

Structure des informations pour les matériaux
Sélectionnez
struct Materiaux
{
    vec4 ambiante;
    vec4 diffuse;
    vec4 speculaire;
}
Calcul de la lumière en prenant en compte le matériau
Sélectionnez
couleurAmbiante = couleurAmbiante * mat.ambiante;
couleurDiffuse = couleurDiffuse * mat.diffuse;
couleurSpeculaire = couleurSpeculaire * mat.speculaire;

Notez qu'encore une fois, il faut que la lumière spéculaire ne soit visible que si l'angle est supérieur à 0.

4-A-1-I. Conclusion sur les lumières

Nous avons vu les différentes lumières et les différents types d'éclairages qui étaient présent dans le pipeline fixe d'OpenGL. Vous pouvez implémentez vos propres effets afin d'avoir le résultat qui vous convient le mieux. Le site wikipedia regorge d'informations sur ce sujet en perpétuel évolution.

Les algorithmes décris dans cette section peuvent être appliqué dans le vertex shader ou dans le pixel shader. Sachant que le pixel shader est exécuté pour tous les pixels dessinés, l'exécution sera plus lente, par contre, ce sera plus beau.

L'ancien pipeline était limité à 8 lampes. Maintenant vous pouvez faire plus, mais cela va ralentir l'exécution. Il existe une méthode appelé « rendu différé » (Deferred Shading) permettant de mettre des centaines de lampes dans une scène.

4-A-2. Application d'une texture

Du côté OpenGL, le code pour appliquer une texture est le même que celui qui n'utilise pas de shader.

Pour les textures, il y a quatre variables à gérer :

  • la matrice de la texture : gl_TextureMatrix ;
  • les coordonnées de la texture : gl_MultiTexCoord0 ;
  • les coordonnées de la texture (interpolés) : gl_TexCoord[ gl_MaxTextureCoords ] ;
  • l'échantillon de la texture (les couleurs), qui est une variable uniforme.


La matrice de texture est un tableau, ayant au maximum gl_MaxTextureCoords. gl_MultiTexCoord0 représente les coordonnées de la première texture, pour le vertex actuel. Le '0' peut être remplacé par un chiffre de 0 à 7.

L'échantillon 'sampler' est un type qui représente la texture dans le fragment shader.

Ce qui nous donne le processus suivant:

Vertex shader : transforme nos coordonnées de texture et passe le résultat au fragment shader.

Vertex shader d'application d'une texture
Sélectionnez
void main (void)
{
    gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
    gl_Position = ftransform();
    //gl_FrontColor = vec4(couleur,1.0);
}

Fragment shader : accède à notre texture pour récupérer la couleur. Pour cela, nous utilisons texture2D, qui nous retournera la couleur de la texture à l'endroit indiqué par les coordonnées de texture.

Fragment shader d'application d'une texture
Sélectionnez
uniform sampler2D tex;
 
void main(void)
{
    gl_FragColor = texture2D(tex,gl_TexCoord[0].st);
}
Cube texturé
Cube texturé

4-A-2-A. Différents types d'application

Dans le pipeline fixe d'OpenGL, nous avions la possibilité de choisir la façon dont la couleur de la texture allait être appliquée sur notre objet. Je vais retranscrire rapidement les différentes formules.

GL_REPLACE :

Remplace la couleur actuelle par la couleur de la texture. C'est exactement le calcul que j'ai fait dans l'exemple précédent.

Application de texture avec GL_REPLACE
Sélectionnez
Couleur = texture2D(tex0, gl_TexCoord[0].xy) ;
Effet du GL_REPLACE
Effet du GL_REPLACE

GL_MODULATE :

Multiplie la couleur venant du vertex shader avec cette de la texture. Cela peut être utile si le calcul de la lumière est effectué dans le vertex shader, et que cette lumière doit avoir un effet sur l'application de la texture.

Application de texture avec GL_MODULATE
Sélectionnez
couleur *= texture2D(tex0, gl_TexCoord[0].xy) ;
Effet du GL_MODULATE
Effet du GL_MODULATE

GL_DECAL :

Utile dans le cas où vous voulez afficher la texture d'un logo sur une surface. La valeur alpha de la texture est utilisée pour faire une interpolation entre la couleur venant du vertex shader (gl_Color), et la couleur de la texture. Finalement, la valeur alpha du vertex shader est utilisée.

Application de texture avec GL_DECAL
Sélectionnez
Vec4 couleurText = texture2D(tex0, gl_TexCoord[0].xy) ;
vec3 coul = mix(color.rgb, couleurText.rgb, couleurText.a) ;
couleur = vec4(coul, color.a);
Effet du GL_DECAL
Effet du GL_DECAL

GL_BLEND :

Ce mode prend en compte la couleur de la texture de l'environnement, en faisant une interpolation entre la couleur venant du vertex shader et celle-ci. Le facteur pour l'interpolation est la texture. Finalement la couleur alpha est déterminée par la multiplication de l'alpha entrant et celui de la texture.

Application de texture avec GL_BLEND
Sélectionnez
Vec4 couleurText = texture2D(tex0, gl_TexCoord[0].xy) ;
vec3 coul = mix(color.rgb, gl_TextureEnvColor[0].rgb, couleurText.rgb) ;
couleur = vec4(coul, color.a * couleurText.a);
Effet du GL_BLEND
Effet du GL_BLEND

GL_ADD :

Ajoute simplement les couleurs. La composante alpha est multiplié pour calculer la composante alpha résultante. Finalement nous remettons les valeurs dans l'intervalle [0, 1] car le calcul peut engendrer des résultats trop grand.

Application de texture avec GL_ADD
Sélectionnez
Vec4 couleurText = texture2D(tex0, gl_TexCoord[0].xy) ;
color.rgb *= couleurText.rgb;
color.a *= couleurText.a ;
couleur = clamp(color,0.0, 1.0);
Effet du GL_ADD
Effet du GL_ADD

Depuis OpenGL 1.3, il y a de nouveau mode d'application de texture. Ils ne sont pas décrits ici, car cela sort du cadre de ce tutoriel. De plus, il est facile de deviner leur implémentation selon leurs descriptions.

4-A-2-B. Génération automatique de coordonnées de texture

Dans OpenGL, nous pouvions demander au pipeline de générér automatiquement les coordonnées de texture. Si vous voulez toujours utiliser cette méthode (qui présente quelques défauts), voici comment faire.

Pour rappel, OpenGL définit 5 types de génération :

  • GL_OBJECT_LINEAR : utile lorsque la texture est fixé à l'objet (par exemple : un terrain) ;
  • GL_EYE_LINEAR : utile pour produire des contours dynamiques aux objets ;
  • GL_SPHERE_MAP : peut générer des coordonnées pour l'application d'environnement ;
  • GL_REFLECTION_MAP : utilise le vecteur de réflexion comme coordonnées de texture ;
  • GL_NORMAL_MAP : utilise la normale comme coordonnée.

Le calcul pour une sphère, tel qui est décrit dans la spécification d'OpenGL est le suivant :

Calcul de coordonnées de texture pour GL_SPHERE_MAP
Sélectionnez
vec2 sphereMap(in vec3 cameraPosition, in vec3 normal)
{
     float m ;
     vec3 r, u ;
     u = normalize(cameraPosition) ;
     r =reflect(u, normal) ;
     m = 2.0 * sqrt(r.x * r.x + r.y * r.y + (r.z + 1.0) * (r.z + 1.0)) ;
     return vec2(r.x / m + 0.5, r.y / m + 0.5);
}

Le calcul utilisé pour GL_REFLECTION_MAP est :

Calcul de coordonnées de texture pour GL_REFLECTION_MAP
Sélectionnez
vec3 reflectionMap(in vec3 cameraPosition, in vec3 normal)
{
     vec3 u = normalize(cameraPosition) ;
     return (reflect(u,normal));
}

Finalement, selon le choix que vous faites pour votre génération, le code généraliste pour avoir les coordonnées de texture est le suivant :

Génération coordonnées texture
Sélectionnez
vec2 sphereMapCoord ;
vec3 reflectionCoord;
 
If ( isTexSphere )
{
    sphereMapCoord = sphereMap(cameraPosition,normal);
}
 
if ( isTexReflection )
{
    reflectionCoord = reflectionMap(cameraPostion,normal);
}
 
// Pour toutes les textures activées
for ( int i = 0 ; i < nombreTexture ; i++ )
{
    if ( isTexObject )
    {
        gl_TexCoord[i].s = dot(gl_Vertex, gl_ObjectPlaneS[i]) ;
        gl_TexCoord[i].t = dot(gl_Vertex, gl_ObjectPlaneT[i]) ;
        gl_TexCoord[i].p = dot(gl_Vertex, gl_ObjectPlaneR[i]) ;
        gl_TexCoord[i].q = dot(gl_Vertex, gl_ObjectPlaneQ[i]);
    }
 
    if ( isTexEye )
    {
        gl_TexCoord[i].s = dot(gl_Vertex, gl_EyePlaneS[i]) ;
        gl_TexCoord[i].t = dot(gl_Vertex, gl_EyePlaneT[i]) ;
        gl_TexCoord[i].p = dot(gl_Vertex, gl_EyePlaneR[i]) ;
        gl_TexCoord[i].q = dot(gl_Vertex, gl_EyePlaneQ[i]);
    }
 
    if ( isTexSphere )
    {
        gl_TexCoord[i] = vec4(sphereMapCoord, 0.0, 1.0);
    }
 
    if ( isTexReflection )
    {
        gl_TexCoord[i] = vec4(reflectionCoord, 1.0);
    }
 
    if ( isTexNormal )
    {
        gl_TexCoord[i] = vec4(normal, 1.0);
    }
}

4-A-3. Brouillard

Le brouillard est un effet qui altère la couleur de l'objet selon la distance entre celui-ci et la caméra.

Dans le pipeline fixe, nous pouvions retrouver trois algorithmes différents pour le calcul du brouillard. Le premier pouvait être sélectionné en indiquant GL_LINEAR à glFogf(GL_FOG_MODE).

La formule utilisée est la suivante :

  • f = fin – z / fin – début


Les variables doivent être dans l'espace de coordonnées de la vue. Toutes ces variables sont intégrées dans le GLSL :

début : gl_Fod.debut
fin : gl_Fod.end
z : gl_FogFragCoord

Le GLSL nous facilite quelques peu la tâche en nous proposant le résultat de gl_Fog.end – gl_Fog.debut dans la variable gl_Fog.scale. Effectivement, ce calcul ne dépend pas de la position du vertex que nous sommes entrain de calculer, donc le mieux est de ne faire qu'une seule fois le calcul.

La formule dans notre code sera donc :

Calcul d'un brouillard linéaire
Sélectionnez
Fog = (gl_Fod.end &#150; gl_FogFragCoord) * gl_Fog.scale ;
Brouillard linéaire
Brouillard linéaire

Le deuxième brouillard présent dans OpenGL est un brouillard exponentiel donnant un résultat plus convaincant.

La formule utilisée est la suivante :

  • f = e-(densité * z)


Z est toujours le même que précédemment (soit gl_FogFragCoord) et la densité est une variable uniforme donnée par le programme. Pour le calcul de l'exponentielle, nous allons utiliser la fonction exp() incluse dans le langage.

Le code résultant en GLSL est le suivant :

Calcul du brouillard exponentiel (première méthode)
Sélectionnez
Fog = exp(-gl_Fog.density * gl_FogFragCoord) ;
Brouillard exponentiel
Brouillard exponentiel

Finalement, le troisième algorithme présent dans le pipeline fixe (correspondant à GL_EXP2) est une amélioration (graphique) de l'algorithme précédent.

La nouvelle formule est la suivante :

  • fog = e-(densité * z)²


Qui correspond au code suivant :

Calcul du brouillard exponentiel (seconde méthode)
Sélectionnez
Fog = exp(-gl_Fog.density * gl_FogFragCoord * gl_Fog.density * gl_FogFragCoord);
2ème Brouillard exponentielle
2ème Brouillard exponentielle

Pour appliquer le brouillard, il faut être sûr que la variable fog est entre 0 et 1. Cela peut se faire en utilisant une fonction du GLSL appelé clamp :

Limitation du brouillard
Sélectionnez
fog = clamp(fog, 0.0,1.0);

Finalement, nous pouvons appliquer le brouillard sur la couleur calculée pour l'objet. Le brouillard a une couleur propre contenue dans gl_Fog.color :

Application du brouillard
Sélectionnez
couleur = mix(vec3(gl_Fog.color), couleur, fog);

4-A-4. Clipping

Le clipping est l'action de découper des morceaux de rendu final afin de ne pas les afficher. Cette fonctionnalité est toujours intégrée de manière fixe dans le pipeline graphique (entre le processeur de vertex et le processeur de fragment).

Si vous utilisez, le clipping vous allez devoir indiquer la position de vertex afin qu'OpenGL puisse savoir si il doit l'afficher ou non. Pour cela il suffit juste d'assigner une valeur à la variable gl_ClipVertex. Habituellement, les utilisateurs stockent le rectangle à découper dans l'espace de coordonnées de l'œil. Cela veut donc dire que nous devons transformer notre vecteur afin de l'avoir dans cet espace :

Calcul du clipping
Sélectionnez
gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;

précédentsommairesuivant

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2011 Alexandre Laurent. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.