Multi-textures - Université de Strasbourg

Transcription

Multi-textures - Université de Strasbourg
Université de Strasbourg
Logiciels et Matériels Graphique
Master 1 ISI
Feuille de TP
Multi-textures
1
Multi-textures : le principe
Bien souvent un rendu nécessite de recourir à plusieurs textures pour sotcker les données utiles au rendu (couleurs,
géométrie, éclairage, ...). Dans ce cas, il est nécessaire d’accéder à plusieurs textures depuis un shader. Il faut donc
que le shader soit lié à plusieurs textures différentes.
On parle dans ce cas de multitexturing.
1.1
Multitexturing et GLSL
En GLSL, l’accès aux textures se fait via un sampler défini en tant que variable uniforme.
Pour qu’un shader prenne en compte plusieurs textures, il suffit de définir plusieurs samplers dans un même
shader ou dans les différents shaders d’un programme de shaders.
La difficulté majeure se situe au niveau d’OpenGL pour activer et lier aux différents samplers les textures à
utiliser.
1.2
Activation de plusieurs textures
Dans le TP sur les textures, nous avons vu qu’au moment du dessin, il faut activer une texture via la fonction
glBindTexture. Mais cette façon de procéder ne permet d’activer qu’une seule texture à la fois.
Pour contourner ce problème, OpenGL offre un mécansime appelé unités de textures. Chaque unité de textures
permet d’activer une texture à la fois. En utilisant plusieurs unités de textures1 pour même shader, il est ainsi
possible d’activer plusieurs textures à la fois.
Pour utiliser une unité de textures, il faut appeler la fonction :
void glActiveTexture(GLenum texture)
où texture spécifie l’unité de textures utilisée et doit être une constante du type
GL_TEXTUREi où i varie en 0 et la plus grande valeur entre GL_MAX_TEXTURE_COORDS−1 et
GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS−12 .
Remarque Les spécifications d’OpenGL assurent que GL_T EXT U REi = GL_T EXT U RE0 + i
1.2.1
Exemple
//Activation de la premiere texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texId1);
1 Le
nombre d’unités de textures disponibles dépend du matériel graphique installé sur la machine.
deux valeurs peuvent être récupérées via la fonction glGetIntegerv.
2 Ces
1
//Activation de la deuxieme texture
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texId2);
//Activation d’un programme de shader utilisant ces deux textures
glUseProgram(pgmId);
//Le dessin
//On oublie pas de desactiver les elements utilises
glUseProgram(0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
1.3
Liaisons entre unité de textures et sampler GLSL
Pour pouvoir utiliser ces différentes textures dans un shader, il faut lier les différentes unités de textures utilisées
aux différents samplers des shaders.
Un sampler peut être vu comme un entier représentant le numéro de l’unité de texture à accéder lors d’un accès
texture. Pour lier une unité de textures à un sampler, il suffit de modifier la valeur de ce sampler en lui attribuant le
numéro de l’unité de texture souhaitée. Comme un sampler est une variable uniforme, cela se fait simplement en
modifiant cette variable uniforme via les fonctions glGetUniformLocation et glUniform*.
1.3.1
Exemple
On suppose que le programme de shaders shaderPgmId définit et utilise deux variables de type sampler2D
appelées, respectivement, tex1 et tex2.
//On memorise l’emplacement des samplers dans le shader.
GLint tex1Loc = glGetUniformLocation(shaderPgmId, "tex1");
GLint tex2Loc = glGetUniformLocation(shaderPgmId, "tex2");
//...
//Association des unites de textures aux differents samplers
glUseProgram(shaderPgmId);
//On associe l’unite de texture GL_TEXTURE0 au sampler tex1
glUniform1i(tex1Loc, 0);
//On associe l’unite de texture GL_TEXTURE1 au sampler tex2
glUniform1i(tex2Loc, 1);
glUseProgram(0);
//On peut maintenant utiliser le shader avec les deux textures
Exercice 1 : Multitexturing
Dessiner un cube. Utiliser un shader pour plaquer sur chacune de ses faces les deux textures couleurs fournies
avec le sujet (woodBox et tex2). Vous pouvez combiner les couleurs des texels des deux textures en utilisant la
fonction mix, pré-définie en GLSL. Il faut cependant que la texture de fond soit la texture woodBox.
2
2
Bump-mapping
L’éclairage de Phong se base, en partie, sur les normales des sommets pour calculer la couleur de l’objet éclairé.
Jusqu’à présent, les normales sont spécifiées pour chaque sommet de l’objet géométrique et sont interpolées par la
carte graphique pour chaque fragment. La technique du bump mapping utilise une texture pour stocker les normales
utilisées pour calculer l’éclairage de l’objet. Les normales ne sont plus simplement interpolées linéairement entre
les sommets d’un triangle mais peuvent varier plus finement sur la surface de ce triangle.
Pour être tout à fait complet, le rendu d’un objet utilisant le bump mapping doit également afficher une information de couleur généralement fournie par une texture couleur.
Exercice 2
Rendre un quadrilatère en utilisant un algorithme de bump mapping. Les normales proviendront de la carte de
normales fournie avec le sujet (rockwall_normal.bmp). Vous devez également utiliser la texture couleur
rockwall.bmp.
Attention, les normales étant stockées dans une image, il a fallu les transformer pour passer de [−1; −1] → [0; 1].
Elles ont donc subit la transformation suivante :
1 → 1
→
n +
f (−
n) = ∗−
2
2
Il faudra donc leur faire subir la transformation inverse au moment de leur utilisation dans le fragment shader.
3