Laboratoire 08

Éclairage Phong dans Fragment Shader

Le module d'éclairage appliqué dans la mise en oeuvre du fragment de shader est le même que celui étudié dans le laboratoire 07 . Cependant, il existe une différence majeure entre les deux implémentations en ce que l'éclairage n'est plus appliqué au niveau de chaque sommet, mais au niveau du fragment. Le résultat final est de qualité supérieure car l'éclairement de chaque fragment ne sera plus calculé en fonction de l'interpolation de la lumière calculée au niveau du sommet, mais en fonction de la normalité et de la position dans l'espace de chaque fragment.

Les valeurs d'entrée reçues par Fragment Shader sont interpolées linéairement entre les valeurs des sommets qui constituent la primitive utilisée pour le dessin.

L’image ci-dessus est obtenue en dessinant un triangle comportant les 3 pointes de couleurs différentes: rouge , vert , bleu

En transmettant la couleur du Vertex Shader au Fragment Shader, la couleur de chaque fragment à la surface du triangle est calculée comme une interpolation linéaire entre les couleurs des sommets constituant la primitive spécifiée (dans ce cas, un triangle).

La même procédure s'applique à toute autre propriété, telle que:

  • la position dans l'espace mondial d'un fragment (si on envoie les positions des sommets)
  • normal dans l'espace du monde d'un fragment (si on envoie les normales au sommet)
  • toute autre valeur transmise du vertex shader au fragment shader
  • etc

Le modèle d' interpolation utilisé implicitement ( lisse ) calcule l'interpolation en tenant compte également de la perspective (une interpolation de perspective est effectuée). L'API OpenGL vous permet de spécifier le modèle d'interpolation en utilisant des termes spécifiques dans le fragment de shader:

  • flat​ - valeur sera interpolée
  • smooth - perspective interpolaire (implicite)
  • noperspective​ - interpolation linéaire dans l' espace de l' écran

Pour plus de détails sur les modèles d'interpolation, accédez aux ressources suivantes:

Ainsi, en utilisant les valeurs interpolées de position et de normale (dans l’espace du monde), nous pouvons calculer le mode d’éclairement de Phong pour chaque fragment d’une primitive rastérisée, le résultat final étant beaucoup plus élevé puisque l’ interpolation des normes entraîne une transition en douceur entre les surfaces adjacentes (les normales interpolées à partir des bords), l’éclairage final donnera l’impression d’une surface lisse. Ainsi, les polygones composants des objets n'apparaîtront plus visibles dans l'image.

Détails d'implémentation

  1. calcule world_position et world_normal dans Vertex Shader comme dans le laboratoire 07
  2. Les 2 valeurs sont transmises au Fragment Shader
  3. Le calcul de la lumière (ambiante, diffuse, spéculaire) est appliqué dans Fragment Shader

Pour recevoir la valeur d'une variable de type uniform il est suffit de déclarer cette variable dans le shader où elle est nécessaire. Donc, n'envoyez PAS la valeur d'une variable de Vertex Shader à Fragment Shader

// Vertex Shader
uniform vec3 light_position;
// Fragment Shader
uniform vec3 light_position;

Éclairage spot

Toutes les sources lumineuses ne sont pas ponctuelles. Si nous voulons mettre en œuvre l'éclairage à l'aide d'une source de lumière ponctuelle, nous devons prendre en compte un certain nombre de contraintes.

Comme on peut le voir sur l'image pour implémenter une source de lumière, nous avons besoin des paramètres supplémentaires suivants:

  • orientation du spot (direction de la lumière)
  • l'angle de coupure du spot qui contrôle l'ouverture du cône de lumière
  • un modèle d'atténuation angulaire de la lumière qui prend en compte la valeur de coupure du spot

Ainsi, le point P est dans le cône de lumière (il reçoit la lumière) si la condition suivante est supprimée:

float cut_off = radians(30);
float spot_light = dot(-L, light_direction);
if (spot_light > cos(cut_off))
{
	// le fragment est illuminé par le spot, la valeur de la lumière est donc calculée conformément au modèle de Phong 
	// l'atténuation de la lumière est calculée 
}

Afin de simuler correctement l'éclairage ponctuel, nous devons traiter et atténuer la lumière correspondant à l'approche de l'angle de coupure. Ainsi, nous pouvons utiliser un modèle d'atténuation quadratique qui donne un résultat convaincant.

float cut_off = radians(30);
float spot_light = dot(-L, light_direction);
float spot_light_limit = cos(cut_off);
 
// Quadratic attenuation
float linear_att = (spot_light - spot_light_limit) / (1 - spot_light_limit);
float light_att_factor = pow(linear_att, 2);

Exercices

Touche F5 - recharge le shader lors de l'exécution de l'application.

Si vous n'avez modifié que les sources de shader, il n'est pas nécessaire d'arrêter l'application car les shader sont compilés et exécutés par la carte vidéo et ils ne sont pas liés au code source C ++ lui-même, et l'infrastructure permet de les recharger au moment de l'exécution.

  1. Implémenter un éclairage Phong dans Fragment Shader
  2. Lorsque vous appuyez sur la touche F pour passer en mode Spot-Light
    • La direction de l'éclairage est transmise sous la forme uniform vec3 light_direction
    • N'oubliez pas d'appliquer un modèle d'atténuation de la lumière basé sur l'approximation des fragments à l'angle de coupure

[Bonus]

  • Modifier le sens de coupure et l'angle du projecteur à partir du clavier
    • logique dans OnInputUpdate
    • rotation ponctuelle: haut, bas, gauche, droite
    • 2 touches pour augmenter / diminuer l'angle d'éclairage du spot
egc/laboratoare/fr/08.txt · Last modified: 2019/11/28 07:35 by alexandru.gradinaru
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0