M2PRO - Images
Année 2006-2007
TP 2 - Fragment Shaders et Textures
Préambule
Téléchargez et installez les libraries objtoy et sdlkit fournies sur la page du cours.
Vérifiez le bon fonctionnement du sdlkit_testmain et de glsl_testmain.
Documentation :
libSDL Programming Guide
openGL Shading Language Specification
Textures, OpenGL chapitre 10
Partie 1 : mon deuxième vertex shader
Modifiez votre vertex shader du TP1 pour lui faire calculer la couleur de chaque sommet du modèle.
Vous aurez besoin de connaître la position de
la source de lumière et la normale de chaque sommet afin de
calculer la couleur associée à chaque vertex.
Pour définir la source de lumière vous avez le choix :
soit vous utilisez une source de lumière d'openGL,
soit vous utilisez plusieurs paramètres uniform pour définir une source de lumière.
Partie : mon premier fragment shader
La couleur calculée par le vertex shader est
interpolée pour chaque fragment, comment obtenir une couleur par
fragment (pour afficher correctement un reflet, par exemple ?)
|
|
calcul par sommet (vertex shading)
|
calcul par pixel (fragment shading)
|
Une autre manière de voir le problème
: quelle est la différence entre le modèle de Gouraud et
celui de Phong ?
Partie 2 : mon premier texture shader
Plaquez une texture sur votre modèle (cf.
Bigguy du TP1, par exemple) et utiliser un fragment shader pour
l'afficher.
Vous pouvez également utiliser une ou
plusieurs textures supplémentaires pour définir point par
point les paramètres de la matière de l'objet :
exemple : vous pouvez utiliser le canal
A de la texture pour représenter l'exposant du modèle de
Phong, ou l'indice de réfraction de la matière, etc.
Voici un résumé des différentes
étapes à réaliser pour utiliser une texture dans
shader :
pour l'application
- créer la texture
- définir les paramètres d'échantillonnage de la texture
- activer l'unité de texture T
- obtenir l'identifiant de l'uniform permettant au shader de lire la texture (de type sampler2D)
- écrire l'identifiant de l'unité de texture dans le paramètre du shader
- décrire les sommets de l'objet et leur associer une coordonnées de texture.
pour le shader
- déclarer un paramètre uniform de type sampler2D
- lire la texture aux coordonnées (s, t) avec texture2D(vec2(s, t))
- calculer la couleur du fragment en fonction de la couleur de la texture
exemple :
application :
glGenTextures(1, &texname);
glActiveTexture(GL_TEXTURE0); // activer l'unité de texture 0
glBindTexture(GL_TEXTURE_2D, texname); // associer une texture 2D à l'unité
glUseProgram(program);
texlocation= glGetUniformLocation(program, "tex");
glUniform1i(texlocation,
0); // indiquer au shader que l'on utilise la texture
associée à l'unité 0
fragment shader :
uniform sampler2D tex; // le type du sampler depend de la texture (1D, 2D, 3D, cube ,etc.)
void main()
{
vec4 color = texture2D(tex, gl_TexCoord[0].st); // lire la texture 2D
gl_FragColor = color;
}
vertex shader :
void main()
{
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
Remarques : A quoi sert gl_TextureMatrix ?
Dans quel espace travaille le vertex shader ? Le fragment shader ?
Dans quel espace les coordonnées de texture sont-elles exprimées ? [Documentation]
Pourquoi le vertex shader écrit-il gl_TexCoord ? De quel type de paramètre s'agit-il ?
Le vertex shader peut également utiliser les
textures mais uniquement sur les cartes nvidia >= geforce 6
Partie 3 : traitement d'images
Il est possible d'utiliser un fragment shader pour
faire autre chose que calculer l'éclairement d'un fragment.
Par exemple, dans le cours "Images Immersives", il
est nécessaire de déterminer la silhouette d'une
personne, connaissant le décors (le fond) et une image de la
personne :
|
|
le "fond" : image de référence
|
l'image à traiter
|
|
la différence entre le "fond" et l'image
|
Il est évidement possible d'écrire la
fonction de calcul sur cpu, mais ce type de traitement pixel par pixel
est très simple à réaliser avec un fragment
shader.
Dans ce cas, l'interêt d'utiliser un fragment shader est de
"libérer" le cpu pour faire autre chose.
L'algorithme naif :
pour chaque pixel (x, y) de l'image silhouette
si | fond(x, y) - image(x, y) | > Seuil
silhouette(x, y)= 1
sinon
silhouette(x, y)= 0
fin si
Pour réaliser le shader permettant d'afficher
la silhouette vous aurez besoin de calculer la différence entre
2 couleurs.
Comment le faire ? Existe-t-il un espace couleur
mieux adapté que le RGB pour estimer la différence
couleur ?
tp2.tar.gz : fond-video86.ppm, video86.ppm, image.c et image.h pour relire les images pgm et ppm
Filtrer une image avec un masque 3x3 (flou ou dérivé, par exemple) est
également très simple à réaliser.
De
manière générale, tous les traitements pixel par
pixel se programment facilement.
Mais il n'est pas toujours
interressant de le faire. Pourquoi ? Dans quel cas ?
Partie Subsidiaire : Shadow Maps / Projective Texture Mapping
"Paul's Projects" pour les explications sur les ombres standards.
"Variance Shadow Maps" pour les ombres douces.