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 ?)

vertex lighting fragment lighting
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
  1. créer la texture
  2. définir les paramètres d'échantillonnage de la texture
  3. activer l'unité de texture T
  4. obtenir l'identifiant de l'uniform permettant au shader de lire la texture (de type sampler2D)
  5. écrire l'identifiant de l'unité de texture dans le paramètre du shader
  6. décrire les sommets de l'objet et leur associer une coordonnées de texture.

pour le shader
  1. déclarer un paramètre uniform de type sampler2D
  2. lire la texture aux coordonnées (s, t) avec texture2D(vec2(s, t))
  3. 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 :

fond
capture
le "fond" : image de référence

l'image à traiter
silhouette







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


shadow map

    "Paul's Projects" pour les explications sur les ombres standards.

    "Variance Shadow Maps" pour les ombres douces.