IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Découvrez OpenGL 1.1 en VB6/VBA

Image non disponible


précédentsommairesuivant

XIV. Les textures

Nous poursuivons le tutoriel à partir du module de code précédent.
Désactivez d'abord le brouillard en commentant la ligne glEnable GL_FOG ou en supprimant tout le code concerné
On y verra mieux sans brouillard.

XIV-A. Chargement des textures

OpenGL ne fournit aucune fonction pour charger des images à partir d'un fichier.
À nous de charger l'image et de fournir à OpenGL les valeurs des couleurs de chaque pixel.

Le module ModOpenGLTextureLoader contient une fonction TextureAddFromFile qui crée une texture à partir d’un fichier image, en utilisant si besoin Gdi+ pour charger le format PNG notamment.

Vous pouvez également charger, dans une texture, des images au format TGA grâce à la fonction loadTGATexture du module ModOpenGLTextureTGA.bas.
Ce module est une traduction du loader de TGA en C de David Henry

Certaines cartes graphiques n'acceptent que les images de texture dont les dimensions sont des puissances de 2 (2, 4, 8, 16, 32…).
Il est conseillé de travailler avec des textures de dimensions 2, 4, 8, 16, 32, 64, 128…

Pour charger le fichier, nous utiliserons la fonction VB LoadPicture.
Cette fonction lit les formats : bmp, ico, rle, wmf, emf, gif, jpg.

Pour lire les informations (taille, profondeur de couleur), nous utiliserons la fonction GetObject de la bibliothèque windows gdi32.

Ensuite pour créer une texture, on utilise la fonction glGenTextures.
Cette fonction prend en premier paramètre le nombre de textures qu'on veut créer.
Et elle renvoie en deuxième paramètre le nom (en fait le numéro) de la première texture créée.

Une texture s'active avec la fonction glBindTexture.

Puis on la génère avec la fonction glTexImage2D.

Et enfin on désactive la texture courante (0 en texture), on la redéfinira quand on en aura besoin.

Tout ceci est effectué par la fonction TextureAddFromFile du module ModOpenGLTextureLoader.

Image non disponible   Importez le module standard ModOpenGLTextureLoader.
Ce module contient une fonction VB de chargement de textures.

Cette fonction TextureAddFromFile renvoie le numéro de la texture créée à partir du fichier donné en paramètre.

Le paramètre pTransparentColor est optionnel : il permet de rendre une couleur transparente.
Pour activer la transparence, il faut :

  • d'abord utiliser la fonction glEnable GL_BLEND;
  • puis préciser le mode de mélange de couleurs, par exemple : glBlendFunc GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA.

Nous mettrons la transparence en pratique dans le chapitre sur l'affichage des textes.

XIV-B. Application d'une texture sur les faces du cube

Pour qu'OpenGL affiche les textures, il faut d'abord les activer.
On pourrait les activer et les désactiver à chaque fois qu'on en a besoin, mais comme on va tout texturer on va faire simple et activer les textures une fois à l'initialisation.
Donc, dans la procédure d'initialisation InitScene ajoutez :

Active les textures 2D
Sélectionnez
' Active les textures 2D
glEnable GL_TEXTURE_2D

Puis on effectue le chargement du fichier contenant la texture (une seule fois dans la procédure InitScene), grâce à la fonction créée précédemment.
On ajoute également en en-tête de module une variable pour conserver l'identifiant de la texture.

En en-tête de module
Sélectionnez
' Identifiant de la texture plancher
Private gTexturePlancher As Long
Chargement de la texture
Sélectionnez
' Charge la texture 
gTexturePlancher = TextureAddFromFile(CurrentProject.Path & "\plancher.jpg")

Voici le fichier de la texture utilisée (c'est une photo de mon plancher) :

Image non disponible

Ensuite il faut affecter la texture pour qu'elle soit utilisée lors du dessin du cube.
Avant le dessin du cube (avant glBegin), on affecte la texture :

Avant le glBegin du cube
Sélectionnez
' Affecte la texture
glBindTexture GL_TEXTURE_2D, gTexturePlancher
après le glEnd du cube
Sélectionnez
' N'affecte aucune texture
glBindTexture GL_TEXTURE_2D, 0

Il est souvent conseillé d'éviter de trop fréquents appels à glBindTexture.
Pensez à utiliser des méta textures.

On ne voit pas notre texture pour autant.
Et c'est normal, car nous n'avons pas défini de coordonnées de texture.

Il faut spécifier à OpenGL comment mapper la texture.
En effet la texture et le polygone sur lequel on souhaite l'appliquer ne correspondent pas forcément.
On pourrait demander d'appliquer une texture rectangulaire sur un triangle par exemple.

Dans le cas des faces du cube, c'est simple : on demande à ce que la texture recouvre toute la face.

Pour chaque vertice de la forme dessinée, on définit les coordonnées du texel correspondant (un texel c'est comme un pixel, mais pour une texture).

  • (0,0) correspond au texel en bas à gauche de la texture.
  • (1,1) correspond au texel en haut à droite de la texture.

Voici comment les points de la texture vont être affectés à la face avant par exemple :

Image non disponible

On utilise une constante cT que l'on va ensuite modifier pour répéter la texture.

Code de dessin du cube avec ajout des textures
Sélectionnez
' Début de la primitive pour le cube
Const cT As Long = 1
glBegin GL_QUADS
    ' Face du haut = vert
    Call glColor3d(0, 1, 0)
    Call glNormal3d(0, 1, 0)
    Call glTexCoord2f(cT, cT)
    Call glVertex3d(1, 1, -1)
    Call glTexCoord2f(0, cT)
    Call glVertex3d(-1, 1, -1)
    Call glTexCoord2f(0, 0)
    Call glVertex3d(-1, 1, 1)
    Call glTexCoord2f(cT, 0)
    Call glVertex3d(1, 1, 1)
    ' Face du bas = orange
    Call glColor3d(1, 0.5, 0)
    Call glNormal3d(0, -1, 0)
    Call glTexCoord2f(0, 0)
    Call glVertex3f(-1, -1, -1)
    Call glTexCoord2f(cT, 0)
    Call glVertex3f(1, -1, -1)
    Call glTexCoord2f(cT, cT)
    Call glVertex3f(1, -1, 1)
    Call glTexCoord2f(0, cT)
    Call glVertex3f(-1, -1, 1)
    ' Face de derrière = rouge
    Call glColor3d(1, 0, 0)
    Call glNormal3d(0, 0, -1)
    Call glTexCoord2f(0, 0)
    Call glVertex3f(1, -1, -1)
    Call glTexCoord2f(cT, 0)
    Call glVertex3f(-1, -1, -1)
    Call glTexCoord2f(cT, cT)
    Call glVertex3f(-1, 1, -1)
    Call glTexCoord2f(0, cT)
    Call glVertex3f(1, 1, -1)
    ' Face de devant = jaune
    Call glColor3d(1, 1, 0)
    Call glNormal3d(0, 0, 1)
    Call glTexCoord2f(0, 0)
    Call glVertex3f(-1, -1, 1)
    Call glTexCoord2f(cT, 0)
    Call glVertex3f(1, -1, 1)
    Call glTexCoord2f(cT, cT)
    Call glVertex3f(1, 1, 1)
    Call glTexCoord2f(0, cT)
    Call glVertex3f(-1, 1, 1)
    ' Face de gauche = violet
    Call glColor3d(1, 0, 1)
    Call glNormal3d(-1, 0, 0)
    Call glTexCoord2f(cT, cT)
    Call glVertex3f(-1, 1, 1)
    Call glTexCoord2f(0, cT)
    Call glVertex3f(-1, 1, -1)
    Call glTexCoord2f(0, 0)
    Call glVertex3f(-1, -1, -1)
    Call glTexCoord2f(cT, 0)
    Call glVertex3f(-1, -1, 1)
    ' Face de droite = bleu
    Call glColor3d(0, 0, 1)
    Call glNormal3d(1, 0, 0)
    Call glTexCoord2f(cT, cT)
    Call glVertex3f(1, 1, -1)
    Call glTexCoord2f(0, cT)
    Call glVertex3f(1, 1, 1)
    Call glTexCoord2f(0, 0)
    Call glVertex3f(1, -1, 1)
    Call glTexCoord2f(cT, 0)
    Call glVertex3f(1, -1, -1)
glEnd

Les pixels ne correspondent pas toujours aux texels.
Il faut donc définir ensuite comment est lissée la texture.

On utilise pour cela la fonction glTexParameterf.
Remarque : cette fonction s'applique à la texture courante, il faut donc qu'elle ait été affectée avec glBindTexture.

Ajoutez ces lignes juste après l'appel à glBindTexture :

Filtrage de la texture
Sélectionnez
' Filtrage de la texture
glTexParameterf GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR
glTexParameterf GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR
  • GL_TEXTURE_MAG_FILTER définit le filtre lors d'un agrandissement de texture.
  • GL_TEXTURE_MIN_FILTER définit le filtre lors d'une réduction de texture.

Les filtres disponibles sont :

  • GL_NEAREST : utilise le texel le plus proche : plus rapide ;
  • GL_LINEAR : utilise la moyenne des quatre texels les plus proches : plus beau (lissé).

Pour GL_TEXTURE_MIN_FILTER, il y a également les filtres de mipmapping GL_*_MIPMAP_*, mais nous ne le détaillons pas tout de suite.

La valeur de GL_TEXTURE_MAG_FILTER par défaut est déjà GL_LINEAR.
Mais la valeur de GL_TEXTURE_MIN_FILTER par défaut est GL_NEAREST_MIPMAP_LINEAR.

Voici donc notre cube texturé :

Image non disponible

XIV-B-1. Modes d'application d'une texture

On constate que la couleur de la texture s'est multipliée avec la couleur des faces.
On peut changer le mode d'application de la texture avec la fonction glTexEnv.
La fonction glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, param définit le mode d'application avec param qui prend les valeurs :

  • GL_MODULATE : multiplie la couleur de texture avec celle du matériau ;
  • GL_DECAL : utilise le canal alpha de la texture : à utiliser pour appliquer des textures avec transparence ;
  • GL_BLEND : mélange la texture et la couleur ;
  • GL_REPLACE : remplace la couleur par la texture : la couleur n'est plus visible.

Attention : contrairement à la fonction glTexParameterf, cette fonction glTexEnv s'applique à l'ensemble des textures.

Essayez les différents modes d'application de texture en ajoutant l'appel à la fonction par exemple après glBindTexture :

Mode d'application de la texture
Sélectionnez
' Mode d'application de la texture
glTexEnvi GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE

Avec le mode GL_REPLACE, on obtient la texture initiale sans coloration supplémentaire.
Par contre on n'a plus d'éclairage.
Pour éclairer la texture sans la colorer, il suffit de colorer les faces en blanc et de laisser le mode GL_MODULATE par défaut.

XIV-B-2. Répétition de la texture

Telle que nous l'avons définie, la texture est redimensionnée pour occuper toute la face.
On souhaite répéter par exemple cinq fois la texture sur chaque face.
Ainsi on peut couvrir une grande surface avec une petite texture.

Il suffit de modifier les coordonnées de texture en leur donnant une valeur égale à 5.
Modifiez la valeur de la constante cT :

constante cT
Sélectionnez
Const cT As Long = 5

La texture est alors répétée cinq fois sur chaque face.

Image non disponible

Si on ne souhaite pas répéter la texture, il faut changer les paramètres GL_TEXTURE_WRAP_S (horizontal) et GL_TEXTURE_WRAP_T (vertical).
Par défaut leur valeur est GL_REPEAT.
La valeur GL_CLAMP demande de borner les valeurs entre 0 et 1.

En ajoutant :

Pas de répétition de texture complète
Sélectionnez
' Pas de répétition de texture complète
glTexParameterf GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP
glTexParameterf GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP

On obtient :

Image non disponible

Retirez les deux dernières lignes ajoutées, on va conserver le mode de répétition GL_REPEAT (par défaut).

XIV-C. Application d'une texture sur une sphère

Pour appliquer une texture sur la sphère, nous n'allons pas définir les coordonnées de textures pour chaque vertice.

Ce serait compliqué et glu va nous faciliter le travail.

Voici l'image de la texture que nous allons appliquer :

Image non disponible

Cette image provient de Visible Earth.
Elle a été redimensionnée à 256*128 pixels.

Ajoutez une variable pour stocker l'identifiant de la texture.

En en-tête de module
Sélectionnez
' Identifiant de la texture de la sphère
Private gTextureSphere As Long

Puis charger la texture dans la fonction d'initialisation :

Chargement de la texture
Sélectionnez
gTextureSphere = TextureAddFromFile(CurrentProject.Path & "\terre.jpg")

Ensuite lors du dessin de la sphère avec gluSphere il faut :

  • affecter la texture avec glBindTexture ;
  • préciser le mode de filtrage avec glTexParameter ;
  • activer les textures avec gluQuadricTexture.

Nous utilisons le même code que celui qui a servi à dessiner la première sphère.
Mais on modifie la couleur de la sphère : on remplace la couleur jaune par une couleur blanche qui n'affectera pas la texture.

Et pour mieux la voir, on augmente sa taille à 1 au lieu de 0.5

Voici le code de dessin de la sphère avec texture, c'est une deuxième sphère qu'on dessine à l'opposé de la première :

Code de dessin de la sphère avec texture
Sélectionnez
' Dessine une sphère à l'opposé de la lampe
#If VBA7 Then
Dim lQuad2 As LongPtr
#Else
Dim lQuad2 As Long
#End If
glPushMatrix
glColor3VB vbWhite
glTranslated -3 * Cos(gLightRotate), 0, -3 * Sin(gLightRotate)
glBindTexture GL_TEXTURE_2D, gTextureSphere
glTexParameterf GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR
glTexParameterf GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR
lQuad2 = gluNewQuadric
gluQuadricTexture lQuad2, GL_TRUE
gluSphere lQuad2, 1, 20, 15
gluDeleteQuadric lQuad2
glPopMatrix

Et voici notre sphère texturée :

Image non disponible

On remarque que la texture n'a pas été placée à partir du haut de la sphère.
La France se retrouve en bas de la sphère, les deux pôles face à nous et derrière.
On va donc tourner la sphère de 90° autour de l'axe X.

Rotation de la sphère de 90°
Sélectionnez
glRotated -90, 1, 0, 0

Attention, les transformations s'appliquent à l'envers.
C'est-à-dire que si on souhaite tourner la sphère puis la déplacer, il faut d'abord définir le déplacement puis la rotation.

La rotation s'effectue par rapport à l'origine, il faut que la sphère soit centrée sur l'origine pour la tourner autour de son centre.
La ligne précédente est donc à insérer après le déplacement de la sphère avec glTranslated.

Maintenant la France est placée là où on l'attend, et les deux pôles en haut et en bas.

Image non disponible

XIV-D. Le mipmapping

Un petit mot sur le mipmapping 

Le mipmapping est une technique utilisée pour choisir la texture appropriée en fonction de la taille de l'objet.
Pour un objet lointain, on peut se contenter d'une petite texture basse définition.
Et pour un objet proche on souhaite utiliser une texture de meilleure définition.

Lorsqu'on génère une texture avec glTexImage2D, on peut utiliser le deuxième paramètre level pour préciser le niveau de la texture.
La fonction glu gluBuild2DMipmaps permet de générer des images de textures à différentes dimensions.

Pour utiliser ensuite ces textures mipmaps, il faut le préciser dans le filtre de texture.
glTexParameterf GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, param avec comme valeur de param :

  • GL_NEAREST_MIPMAP_NEAREST et GL_LINEAR_MIPMAP_NEAREST pour choisir la texture mipmap la plus appropriée ;
  • GL_NEAREST_MIPMAP_LINEAR et GL_LINEAR_MIPMAP_LINEAR pour mélanger les deux textures mipmap les plus appropriées.

Le MipMapping peut résoudre certains problèmes de scintillement des textures.


précédentsommairesuivant

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2017 Thierry GASPERMENT. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts. Droits de diffusion permanents accordés à Developpez LLC.