Subsections
La création d'une texture nécessite dans un premier temps une image source. Cette image source peut soit être crée à l'intérieur du programme, soit être lue dans un fichier. La définition d'une texture à partir de cette image source s'effectue ensuite en plusieurs étapes3 dont certaines découlent du besoin d'utiliser plusieurs textures de façon simultanée :
- Identifier,
- spécifier la texture courante,
- spécifier le plaquage,
- spécifier l'image source,
- spécifier le mode de rendu.
Pour pouvoir manipuler plusieurs textures, il est nécessaire de les identifier. OpenGL utilise pour cela des entiers. Le choix des entiers peut être fait soit directement, soit à l'aide de la fonction glGenTextures. Cette dernière gère les identifiants de textures et fournit des entiers qui ne sont pas encore utilisés.
int textures[n+1]; /* un tableau d'identifiants vide */
glGenTextures(n, textures); /* genere n entiers */
/* disponibles */
Il s'agit de spécifier la texture (1D ou 2D) sur laquelle s'appliqueront les opérations ultérieures. Cela se fait par l'identifiant de la texture.
glBindTexture(GL_TEXTURE_2D, textures[2]); /* textures[2] */
/* devient active*/
Il s'agit de spécifier la méthode à utiliser pour plaquer la texture courante. Cela se fait à l'aide la fonction glTexParameter. Cette dernière permet de plaquer les textures de différentes manières suivant la fonction de transfert choisie entre l'image destination d'une texture et son image source.
- Répéter ou clamper la texture : les coordonnées textures (s, t) associées à un point sont comprises entre 0 et 1 pour parcourir l'ensemble de l'image de texture. Lorsque ces coordonnées sont en dehors de l'intervalle [0 1], OpenGL peut soit répéter soit clamper la texture (voir figure 17) :
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,
GL_REPEAT - GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,
GL_REPEAT - GL_CLAMP);
Figure 17:
Plaquage de texture : lorsque les coordonnées textures sont supérieures aux dimensions de l'image (donc supérieures à 1), OpenGL peut soit répéter la texture (GL_REPEAT) soit ramener les coordonnées à 1 (GL_CLAMP) en fonction de ce qui a été spécifié avec la fonction glTexParameter.
 |
- Déterminer les valeurs des pixels à remplir : les coordonnées texture (s, t) associées à un pixel ne sont pas nécessairement des valeurs entières et ne correspondent donc pas nécessairement à un texel de l'image de texture. Les solutions consistent alors à prendre soit la valeur du texel le plus proche de (s, t), soit l'interpolation des valeurs des 4 pixels entourant (s, t). OpenGL offre ces deux possibilités dans le cas où la surface à remplir est plus grande que l'image de texture (pixel de taille inférieur au texel) et plus dans le cas où la surface est plus petite que l'image de texture (pixel de taille supérieur au texel).
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,
GL_NEAREST - GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,
GL_NEAREST - GL_LINEAR -
GL_NEAREST_MIPMAP_NEAREST -
GL_NEAREST_MIPMAP_LINEAR -
GL_LINEAR_MIPMAP_NEAREST -
GL_LINEAR_MIPMAP_LINEAR);
Lorsque la surface à remplir est plus grande que l'image de texture (GL_TEXTURE_MAG_FILTER), deux méthodes sont possibles : GL_NEAREST ou GL_LINEAR. La première consiste à choisir le texel le plus proche des coordonnées (s, t) spécifiées (ou calculées), la deuxième consiste à prendre la valeur interpolée des quatre texels entourant la position (s, t) (voir figure 18).
Lorsque la surface à remplir est plus petite (GL_TEXTURE_MIN_FILTER), plusieurs méthodes sont possibles, GL_NEAREST et GL_LINEAR comme précédemment ainsi que des méthodes faisant intervenir des mipmaps. Le principe des mipmaps est de stocker l'image de texture à différents niveaux de résolution : l'image même, l'image de tailles divisées par 4, l'image de tailles divisées par 16, et ainsi de suite jusqu'à ce que l'image soit de la dimension d'un pixel. Ensuite, pour déterminer les valeurs d'intensités pour un pixel, on peut (voir figure 19) :
- choisir l'image dans la mipmap dont les dimensions en pixels sont les plus proches de celles de la surface à remplir(_MIPMAP_NEAREST);
- interpoler entre les deux images dans la mipmap dont les dimensions en pixels sont les plus proches de celles de la surface à remplir (_MIPMAP_LINEAR);
- et enfin choisir le texel le plus proche (GL_NEAREST_MIPMAP_), ou interpoler entre les 4 plus proches (GL_LINEAR_MIPMAP_), dans les images choisies de la mipmap .
Il est à noter que l'option GL_LINEAR_MIPMAP_LINEAR faisant intervenir deux interpolations produira les résultats les plus lisses mais que cela à un coût en temps de calcul.
Figure 18:
Magnification : la texture, dans l'image finale, a des dimensions supérieures à celles de l'image dont elle provient.
 |
Figure 19:
Minification : la texture, dans l'image finale, a des dimensions inférieures à celles de l'image dont elle provient.
 |
Pour spécifier l'image de texture, il est possible de définir directement l'image concernée (soit un tableau de pixels) ou bien de définir ou de calculer une mipmap (l'image à différents niveaux de résolution) à partir de cette image.
La fonction suivante permet de définir une image de texture :
glTexImage2D(GL_TEXTURE_2D,
Level, /* niveau de resolution */
Formatint, /* format interne */
Largeur, Hauteur, /* dimensions puissances de 2*/
Bord, /* largeur du bord (0 ou 1 )*/
Formatext, /* format de l'image */
Type, /* type des donnees */
Image); /* tableau de donnees */
où :
- Level : caractérise le niveau de résolution de l'image, soit 0 pour une seule image. Ce paramètre sert à construire une mipmap lorsque l'on dispose de l'image à plusieurs niveaux de résolutions.
- Formatint : le format interne ou, en d'autres termes, ce que l'on souhaite utiliser dans l'image de texture (quelle composante ...). Les valeurs de ce paramètre sont principalement : GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA 4.
- Largeur, Hauteur : les dimensions de l'image de texture qui doivent être des puissances de 2 de valeur minimum 64. Si l'image que l'on souhaite utilisée ne vérifie pas ce critère, il est toujours possible d'en modifier les dimensions à l'aide de la fonction :
gluScaleImage(Format, Largeur1, Hauteur1, Type1, Image1,
Largeur2, Hauteur2, Type2, Image2)},
où Image1 est l'image initiale et Image2 est l'image redimensionnée.
- Bord : la largeur du bord, soit la valeur 0 ou 1.
- Formatext : le format externe de l'image de texture soit principalement GL_RGB, GL_RGBA, GL_RED, GL_GREEN, GL_BLUE, GL_LUMINANCE, GL_ALPHA, GL_LUMINANCE_ALPHA.
- Type : le type des données soit GL_UNSIGNED_BYTE (entiers non signés sur 8 bit), GL_BYTE, GL_BITMAP (bits codés dans des unsigned bytes), GL_SHORT (entiers signés sur 16 bits), GL_UNSIGNED_SHORT.
- Image : le tableau de valeurs pour l'image de texture.
La fonction glTexImage2D peut aussi servir à construire une mipmap en utilisant différentes valeurs du paramètre Level. Par contre, il existe une fonction de la libraire glu qui construit une mipmap directement à partir de l'image initiale et qui, de plus, redimensionne automatiquement l'image si celle-ci n'a pas des dimensions puissances de 2 :
gluBuild2DMipmaps(GL_TEXTURE_2D,
Formatint, /* format interne */
Largeur, Hauteur, /* dimensions de l'image */
Formatext, /* format de l'image */
Type, /* type des donnees */
Image); /* tableau de donnees */
Enfin, la dernière fonction concerne le mode de rendu à utiliser : soit la texture uniquement, soit la combinaison de la texture et d'un rendu.
glTexEnvi(GL_TEXTURE_ENV,
GL_TEXTURE_ENV_MODE,
GL_DECAL - GL_REPLACE - GL_MODULATE - GL_BLEND)
la valeur par défaut est GL_MODULATE qui combine le rendu, si celui ci est défini, et la texture. Pour une texture de format RGB, le rendu s'effectue pour chaque composante suivant (voir figure 20):
DECAL |
REPLACE |
MODULATE |
BLEND |
texture |
texture |
texture × rendu |
rendu × (1 - texture) |
Figure 20:
Spécifier le rendu : en fonction du mode rendu choisi, il est possible d'afficher le rendu uniquement, la texture uniquement (GL_DECAL - GL_REPLACE) ou une combinaison des deux (GL_MODULATE - GL_BLEND).
 |
Le code suivant illustre l'ensemble des appels de fonctions utiles à l'usage d'une texture :
void init_texture()
{
glGenTextures(1,&num_texture);
glBindTexture(GL_TEXTURE_2D, num_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
image = LoadPNMImage("image.ppm",&ImgWidth,&ImgHeight,&MaxVal);
//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, ImgWidth, ImgHeight,
0, GL_RGB, GL_UNSIGNED_BYTE, Image);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, ImgWidth, ImgHeight,
GL_RGB, GL_UNSIGNED_BYTE, image);
glEnable(GL_TEXTURE_2D);
}
Edmond Boyer
2001-03-07