TP3 : Shaders avancés

Détection des silhouettes

Nous allons réaliser la détection des silhouettes par un traitement d'image, puis compositer le résultat obtenu avec le rendu toon du TP1. Le principe est d'utiliser un filtre détecteur de contour comme celui de Sobel :


H =
-1 -2 -1
 0  0  0
 1  2  1

   V =
1  0 -1
2  0 -2
1  0 -1

   résultat = sqrt(H² + V²)

Un tel filtre va détecter la différence d'intensité entre deux pixels consécutifs. Plus la différence entre la valeur du pixel considéré et les valeurs des pixels l'entourant est grande, plus le contour sera marqué. Dans notre cas, pour détecter les silhouettes, ce ne sont pas les variations de couleur qui nous intéressent, mais celles de profondeur. Ainsi, il faut appliquer le filtre sur le depth buffer pour que les changements de profondeur soient marqués par un contour.

Cependant, la convolution d'une image (de couleur ou de profondeur) avec un filtre nécessite d’accéder à plusieurs pixels de l’image, ce qui est impossible en une seule passe de rendu. Nous allons donc utiliser la technique du "deferred shading" pour dessiner dans des textures le rendu toon et la carte de profondeur, avant d'appliquer une seconde passe sur les images 2D obtenues pour en extraire les silhouettes et les compositer avec le toon shading. Il faut pour cela utiliser un FrameBufferObject (FBO) et l'attribut gl_FragCoord du fragment shader pour connaitre la position du fragment courant dans l'image.

toonSilhouettes

Modifier la valeur du seuil du filtre. Quelles sont les limitations de cette approche ?

Environment mapping

envMap   refraction

L'environment mapping (carte d'environnement) est un procédé qui permet de générer les réflexions / réfractions d'un environnement sur un objet en temps réel en utilisant des textures. L'environement map peut être vu comme une sphère ou une boîte englobant toute la scène. Il existe plusieurs façons de représenter un environnement : textures sphériques, textures paraboidales, textures cubiques... Cette dernière représentation est la plus simple à utiliser avec OpenGL et de nombreuses "cube maps" sont disponible sur le net (ici par exemple et sur la page de Paul Debevec).

Dans le fragment shader, utilisez un samplerCube pour lire la couleur de l'environnement dans la direction de réflexion fonction GLSL reflect) et/ou de refraction (refract) du vecteur de vue. Vous pourrez alors combiner les deux couleurs obtenues en fonction de l'approximation de Schlick de l'équation de Fresnel :

F = f + (1 - f) (1 - VN)5 avec f = (1 - n1 / n2)² / (1 + n1 / n2)²

Images à grande dynamique

Le viewer OpenGL fournis vous permet de charger des cartes d'environnement HDR (au format RADIANCE). Vous pouvez les visualiser et éditer en utilisant le logiciel libre et multi-plateformes Luminance HDR.

Contrairement au textures habituelles, ces images HDR sont chargées dans des buffers floattants avec 32 bits par canal. Cependant, elles doivent être "tone mappées" pour pouvoir être affichées sur un écran LDR (8 bits par canal). Par defaut un mapping linéaire non contrôlable est effectué.

Nous allons tout d'abord permettre à l'utilisateur de contrôler uniformément l'exposition et le gamma de la scène. Pour cela, effectuons à nouveau le rendu principal dans un FBO (floattant) et modifions la texture obtenue en la multipliant par une constante pour changer l'exposition et en l'élevant à la puissance pour modifier le gamma.

refraction envMap refraction
exposition=0.75 / gamma=0.8 exposition=1 / gamma=1 exposition=1.5 / gamma=1.2

Pour permettre une meilleure reproduction de la tonalité de l'image, vous pouvez implémenter un opérateur de "tone mapping" plus avancé (quelques références).

Ombres

ombres

Nous allons implémenter la technique de "shadow mapping" présentée en cours. Pour cela, il nous faut réaliser deux passes de rendu :

La difficulté principale est de se placer dans les bons espaces pour effectuer les accès aux textures : depuis le repère de la vue de la caméra vers le repère écran de la lampe.

ombres