TP2-OpenGl 2.1 Elimination d`effet d`alias par mip-map
Transcription
TP2-OpenGl 2.1 Elimination d`effet d`alias par mip-map
ENSICAEN 2007 TP2-OpenGl 2.1 Elimination d’effet d’alias par mip-map Avec cette technique, on prépare, à partir d’une texture T0 , une suite T1 , · · · Tn de textures de tailles décroissantes. Ainsi, si la texture initiale T0 est de taille 256 × 64, les suivantes seront de tailles respectives 128 × 32, 64 × 16, 32 × 8, 16 × 4, 8 × 2, 4 × 1, 2 × 1 et 1 × 1. En général, un texel t de Ti+1 correspond à 4 texels adjacents de Ti , la couleur de t étant la moyenne des couleurs des texels correspondants dans Ti+1 . L’algorithme employé tente de garder constant le nombre de texels intervenant dans la couleur d’un pixel. Nous appelons ce nombre le ratio de texels/pixel. Cette opération améliore grandement l’effet de compression de texture (“texture minification”). Pour cela, OpenGl trouve pour un pixel donné p, les deux plans de texture T et T ′ qui donnent les meilleurs ratios de texels/pixel par défaut et par excès. Suivant la méthode spécifiée, la texture finale sera soit celle provenant du plan de ratio le plus proche, soit une interpolation linéaire entre deux texels, l’un provenant de T et l’autre de T ′ . 2.1.1 Préparation des textures intermédiaires Si on a réussi à construire la texture du niveau 0, la fonction glu ci-dessous permet d’obtenir les autres niveaux de texture. gluBuild2DMipmaps(GLenum target, GLint components, GLint width, GLint height, GLenum format, GLenum type, void *texels) Exemple : texdata = loadppm("tuile.ppm", -1, texWidth, texHight, texMaxval); gluBuild2DMipmaps(GL_TEXTURE_2D, 3, texWidth, texHight, GL_RGB, GL_UNSIGNED_BYTE, texdata) La première ligne charge dans texdata une texture en récupérant ses dimensions et la seconde construit les textures de niveaux inférieurs. Les paramètres de gluBuild2DMipmaps ont la même signification que ceux de glTexImage2D. Le paramètre components indique le nombre de composantes d’un texel (4 pour le format RGBA, 3 pour RGB etc.). 1 2.1.2 Traitement de compression de texture Lorsqu’on a chargé une texture mipmap, on a plusieurs possibilités pour traiter le problème de compression de texels. Rappelons que pour les textures ordinaires, nous pouvons spécifier deux méthodes GL_LINEAR et GL_NEAREST par : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) et glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) Avec le mipmaping, on peut indiquer quatre autres méthodes : GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR La qualité de texturage s’améliore dans l’ordre, la meilleure qualité étant produite par GL_LINEAR_MIPMAP_LINEAR. Exercie 1. Complétez le code du fichier exo1.cpp de la manière suivante : placez 400 = 20 × 20 carrés de dimension 1 × 1 sur [−10, +10] × [−10, +10] du plan z = −5 (la caméra se trouvant à l’origine). Texturez chaque carré par la méthode de mipmap, avec le fichier d’image tuile.ppm. Complétez le code de la fonction keyboard pour qu’on puisse modifier par les touches du clavier, le traitement de la compression des textures. Faites subir aux carrés des rotations et des translations et examiner le résultat. ———————————————————————————————— Après avoir lancé gluBuild2DMipmaps, il est possible de modifier l’image du niveau i, en exécutant glTexImage2D. Par exemple, pour le niveau 2 : texdata2 = loadppm("texture2.ppm", -1, width2, hight2, maxval2); glTexImage2D(GL_TEXTURE_2D, 2, 3, width2, height2, 0, GL_RGB, GL_UNSIGNED_BYTE, texdata2); Avec ces deux instructions, nous avons modifié l’image mipmap du niveau 2. Il faut bien entendu s’assurer que cet image a les bonnes dimensions. Exercice 2. Reprenez l’exercice précédent. Chargez en mode mipmap le fichier texbase.ppm et remplacez les différents niveaux de texture (de 0 à 5) par les images se trouvant dans les fichiers tex256.ppm, . . ., tex8.ppm. Ces fichiers 2 contiennent des images monochromes. Faites mouvoir l’objet et observez (et expliquez) la composition des couleurs observées en différents modes de texture. 2.2 Texturage multiple Le but du texturage multiple est d’appliquer plusieurs textures distinctes sur un même objet. En principe, tout se passe comme pour l’application d’une texture simple, sauf qu’il faut charger n fichiers textures et définir pour chaque sommets n coordonnés de textures. Les coordonnées de texture ne sont pas nécessairement identiques. Pour y parvenir, procédez de la manière suivante (pour deux textures) : 1. Inclure (par #include) le fichier glext.h, en vérifiant que ce fichier figure bien dans un répertoire accessible au compilateur. 2. Déclarer deux nouvelles fonctions, initialisées à NULL, de la manière suivante : PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB = NULL; PFNGLACTIVETEXTUREARBPROC glActiveTextureARB = NULL; 3. Déclarez un tableau de noms de texture, contenant autant de cases que nécessaires. Pour deux textures, on déclarera par exemple : GLuint texName[2]; 4. Il faut aller chercher l’adresse exacte des deux fonctions déclarées précédemment. Cela se fait par : glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)wglGetProcAddress("glActiveTextureARB"); glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC)wglGetProcAddress("glMultiTexCoord2fARB"); 5. Réservez de la place mémoire pour les deux structures de données qui vont recevoir les textures. glGenTextures(2, texName); 6. Chargez les deux images servant de texture. Avec la fonction loadppm cela donne : 3 texdata1=loadppm("mur.ppm", -1, texWidth1, texHeight1, texMaxval1); texdata2=loadppm("light.ppm", 127, texWidth2, texHeight2, texMaxval2); Dans cet exemple, on remarquera que la première image chargée (mur.ppm) est une image en RGB alors que le second (light.ppm) est traduit en RGBA, avec un alpha égal à 127. 7. Il faut maintenant activer chaque texture et définir les modalités de son application. Avec notre exemple, les instructions relatives à la première texture sont : glActiveTextureARB(GL_TEXTURE0_ARB); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texName[0]); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texWidth1, texHeight1, 0, GL_RGB, GL_UNSIGNED_BYTE, texdata1); errCode = glGetError(); if (errCode != GL_NO_ERROR){ errString= gluErrorString(errCode); cout <<" Texture1: "<<errString<<endl; exit(1); } glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); On examinera soigneusement l’ensemble de ces instructions. La première ligne est spécifique au multi-texturage. Il est prudent de vérifier que les instructions ont été correctement exécutées (d’où le message d’erreur). La dernière ligne n’est nécessaire que si l’objet a déjà reçu une couleur. 8. On exécute les mêmes opérations pour la seconde texture : glActiveTextureARB(GL_TEXTURE1_ARB); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texName[1]); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth2, texHeight2, 0, GL_RGBA, GL_UNSIGNED_BYTE, texdata2); errCode = glGetError(); 4 if (errCode != GL_NO_ERROR){ errString= gluErrorString(errCode); cout <<" Texture2: "<<errString<<endl; exit(1); } glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); La présence de l’instruction glTexEnvf est nécessaire, car il s’agit d’afficher la seconde texture pardessus la première. 9. Il faut enfin définir les coordonnées de texture. Cette opération se fait à l’occasion de chaque déclaration de sommet. Par exemple (les nombres sont donnés à titre d’exemple) : glMultiTexCoord2fARB(GL_TEXTURE0,0.5,0.5); glMultiTexCoord2fARB(GL_TEXTURE1,0.3,0.2); glVertex3f(0.1,0.2,0.3); Exercice 3. Réalisez le multitexturing sur un tore à l’aide des fichiers mur.ppm et light.ppm. Exercice 4. Réalisez une scène comprenant une tour en brique, illuminée par la lumière de jour. Indications : Inspirez vous de l’image de la tour fournie. Trouvez une image de mur en brique sur le web. Eclaircissez l’image sous gimp comme s’il était surexposé. Fabriquez une texture (toujours sous gimp) comprenant une partie blanche et partie plus sombre. Appliquez les deux images en multi-texture sur une scène de tour simple (cube allongé). 5