Le placage de texture consiste à placer une image (la texture ) sur un objet. Cette opération se comprend aisément lorsqu'il s'agit de plaquer une image rectangulaire sur une face rectangulaire, tout au plus imagine-t-on au premier abord qu'il y a un changement d'échelle à effectuer sur chacune des dimensions.
Mais peut-être au contraire le choix est de répéter l'image un certain nombre de fois sur la face.
Se pose ensuite la question d'objets qui ne sont pas des faces rectangulaires : comment définir la portion d'image et la manière de la plaquer ?
Comment procéder de manière générale
- Il s'agit d'abord de créer un Objet-Texture et de spécifier la texture que l'on va utiliser.
- Ensuite choisir le mode de placage de la texture avec glTexEnv[f,i,fv,iv]()
- Le mode replace remplace la couleur de l'objet par celle de la texture.
- Le mode modulate utilise la valeur de la texture en modulant la couleur précédente de l'objet.
- Le mode blend mélange la couleur de la texture et la couleur précédente de l'objet.
- Le mode decal avec une texture RGBA utilise la composante alpha de la texture pour combiner la couleur de la texture et la couleur précédente de l'objet.
- Puis autoriser le placage de textures avec glEnable(GL_TEXTURE_2D) si la texture a deux dimensions. (ou GL_TEXTURE_1D si la texture est en 1D).
- Il est nécessaire de spécifier les coordonnées de texture en plus des coordonnées géométriques pour les objets à texturer.
Les coordonnées de texture vont de 0.0 à 1.0 pour chaque dimension. |
 |
On assigne avec glTexCoord*() pour chaque sommet des objets à texturer un couple de valeurs qui indique les coordonnées de texture de ce sommet.
Si l'on désire que toute l'image soit affichée sur un objet de type quadrilatère, on assigne les valeurs de texture
(0.0, 0.0) (1.0, 0.0) (1.0, 1.0) et (0.0, 1.0) aux coins du quadrilatère. |
 |
Si l'on désire mapper uniquement la moitié droite de l'image sur cet objet, on assigne les valeurs de texture
(0.5, 0.0) (1.0, 0.0) (1.0, 1.0) et (0.5, 1.0) aux coins du quadrilatère. |
 |
Exercice
- Examinez le programme texture1.c pour comprendre l'utilisation des coordonnées de texture.
(il utilise l'image snoopy2.ppm. Vous pouvez aussi télécharger l'archive du projet Dev-Cpp)
- Quelles coordonnées de texture permettent de plaquer uniquement la tête de snoopy sur le quadrilatère ?
Répétition de la texture
Il faut indiquer comment doivent être traitées les coordonnées de texture en dehors de l'intervalle [0.0, 1.0]. Est-ce que la texture est répétée pour recouvrir l'objet ou au contraire "clampée" ?
Pour ce faire, utilisez la commande glTexParameter() pour positionner les paramètres GL_TEXTURE_WRAP_S pour la dimension horizontale de la texture ou GL_TEXTURE_WRAP_T pour la dimension verticale à GL_CLAMP ou GL_REPEAT.
Exercice
- Dans la moitié inférieure du quadrilatère, plaquez trois fois l'image du snoopy.
Depuis la version 1.1 d'OpenGL, il est possible de déclarer, de nommer et de rappeler
simplement des Objets-Textures.
- glGenTextures(GLsizei
n, GLuint *textureNames) renvoie n noms (des numéros,
en fait) de textures dans le tableau textureNames[]
- glBindTexture(GL_TEXTURE_2D,
GLuint textureNames) a trois effets différents :
- la première fois qu'il est appelé avec une valeur textureNames non
nulle, un nouvel Objet-Texture est crée, et le nom textureNames lui est
attribué.
- avec une valeur textureNames déjà liée à une objet-Texture, cet objet
devient actif
- avec la valeur zéro, OpenGL arrête d'utiliser des objets-textures et retourne à
la texture par défaut, qui elle n'a pas de nom.
- glDeleteTextures(GLsizei
n,const GLuint *textureNames)efface n objets-textures
nommés par les éléments du tableau textureNames
Exercice
Notez que les pixels de l'image de texture s'appellent des texels (au lieu de picture-elements, on a des texture-elements).
Lorsque la partie de l'image de texture qui est mappée sur un pixel d'un objet est plus petite qu'un
texel, il doit y avoir agrandissement.
Lorsqu'au contraire la partie de l'image de texture qui est mappée sur un pixel d'un
objet contient plus d'un texel, il doit y avoir une réduction.
La commande glTexParameter() permet de
spécifier les méthodes d'agrandissement ( GL_TEXTURE_MAG_FILTER ) et de réduction
( GL_TEXTURE_MIN_FILTER ) utilisées :
- GL_NEAREST choisit le texel le plus proche
- GL_LINEAR calcule une moyenne sur les 2x2 texels les plus proches.
L'interpolation produit des images plus lisses, mais prend plus de temps à calculer. Le
compromis valable pour chaque application doit être choisi.
Les objets texturés sont visualisés comme tous les objets de la scène à différentes
distances de la caméra. Plus les objets sont petits, moins il est nécessaire d'utiliser une
taille importante pour l'image de texture utilisée. En particulier, l'utilisation d'images
de tailles adaptées à la taille de l'objet peut accélérer le rendu de l'image et éviter
certains artéfacts visuels lors d'animations.
OpenGL utilise une technique de mipmapping pour
utiliser des images de taille appropriée. Les images du quart, du seizième, du
soixante-quatrième, etc de la taille de l'image initiale sont stockées, jusqu'à l'image
d'un pixel de côté, et en fonction de la taille de l'objet dans la scène, la texture de la
taille adaptée est choisie.
Vous pouvez fournir vous-mêmes les images de texture aux différentes tailles
avec plusieurs appels à glTexImage2D()
à différentes résolutions, ou bien utiliser la routine de l'OpenGL Utility
Library : gluBuild2DMipmaps(), qui calcule les
images réduites.
Filtrage : suite
Lors d'utilisation de mipmaps, il y a quatre autres filtres de réduction :
- GL_NEAREST_MIPMAP_NEAREST et GL_LINEAR_MIPMAP_NEAREST
utilisent l'image mipmap la plus proche, et dans cette image, le premier choisit le
texel le plus proche, et le deuxième réalise une interpolation sur les quatre texels
les plus proches.
- GL_NEAREST_MIPMAP_LINEAR et GL_LINEAR_MIPMAP_LINEAR
travaillent à partir de l'interpolation de 2 mipmaps.
Pour un chargement simple et efficace de tous les formats d'image les plus courants, utilisez XnView, développé par Pierre-Emmanuel Gougelet.
Sa bibliothèque gfl est disponible pour les principaux systèmes d'exploitation actuels.
Elle est gratuite pour un usage non commercial.
La télécharger
Testez-la sous Windows avec le projet DevC++ GFLtexbind.
Si vous ne désirez charger que des images au format PPM (avec les données en binaire et éventuellement des lignes de commentaires),
les fichiers loadppm.cpp et loadppm.h
suffiront à votre bonheur.
La routine gluBuild2DMipmaps(),
que vous trouvez dans l'exemple texturebind.c, permet de spécifier quelle image vous utilisez
comme texture. Cette routine accepte les images de toutes tailles.
La fonction
glTexImage2D(), par contre, nécessite
une image dont la hauteur et la largeur sont des puissances (éventuellement
différentes) de 2 : votre image peut avoir comme taille 256x64, mais pas 100x100.
Ecrivez une classe Texture qui permet de générer un objet OpenGL
texture à partir d'un fichier contenant une image, d'activer cette
texture, et de détruire l'objet OpenGL texture.
class Texture {
GLuint tNum;
public:
Texture(char *nom);
void activer();
~Texture();
};
Récupérez deux images de textures (images qui peuvent se répéter) et plaquez
l'une sur le bras de votre robot, l'autre sur l'avant-bras et les doigts.
L'incontournable malheur de cet exercice est que ni glutSolidCube, ni glutSolidSphere ne possèdent de coordonnées de textures.
Moralité : si vous voulez texturer un cube, il faut l'écrire à la main. (Pour la sphère, utilisez gluSphere, vous en serez satisfaits).
Enjoy !
17 décembre 2012