VII. Les Textures 3D▲
On se représente assez naturellement une texture 2D par un rectangle.
Une texture 3D présente une dimension supplémentaire : on peut donc se la représenter par un cube (ou un pavé).
Ces textures sont d'ailleurs également appelées Volume Texture.
De ce fait, ces textures occupent un espace mémoire relativement important.
Par exemple, une texture 3D cubique de 64 pixels de côté sans canal alpha occupe en mémoire : 64 * 64 * 64 * 3 = 786 432 octets = 768 Ko.
VII-A. Utilité des textures 3D▲
Les textures 3D sont très intéressantes lorsqu'on souhaite texturer un objet sans discontinuité entre les différentes faces.
Par exemple on peut texturer notre cube pour faire croire qu'il est en bois :
Regardez bien aux arêtes du cube : il n'y a pas de discontinuité, comme si le cube était taillé dans la masse.
VII-B. Préparation de l'environnement de développement VB▲
Préparez votre application pour afficher un cube, tel qu'il est expliqué ci-dessus dans la section V : Préparation de l'environnement de développement VB.
Les textures 3D sont apparues avec la version 1.2, elles sont supportées par de nombreuses cartes graphiques (même sur portable ou ordinateur de bureautique).
Commençons tout de même par vérifier que la carte graphique les supporte, en plaçant ce code avant l'appel à InitScene :
' Teste si les textures 3D sont supportées, soit par la version, soit l'extension EXT
If
val
(
LongToString
(
glGetString
(
GL_VERSION))) <
1
.2
And
InStr
(
LongToString
(
glGetString
(
GL_EXTENSIONS)), "GL_EXT_texture3D"
) =
0
Then
MsgBox
"Textures 3D non supportées"
, vbOKOnly
Exit
Function
End
If
Bien entendu, Exit Function est à remplacer par Exit Sub si le test est codé dans la procédure Main d'une application VB6.
Les textures 3D sont supportées à partir de la version 1.2, ou dans l'extension GL_EXT_texture3D.
Si on n'est pas dans ce cas, on affiche un message et on quitte la fonction.
Importez maintenant le module ModOpenGL_1_2 qui contient les fonctions de la version 1.2.
N'oubliez pas de « mapper » ensuite les fonctions en exécutant la procédure RemapVBToGL de ce module.
' Initialise les fonctions
ModOpenGL_1_2.RemapVBToGL
Nous voici prêts à programmer les textures 3D !
VII-C. Génération de la texture▲
Déclarons tout d'abord un identifiant pour la texture, en début de module :
' Identifiant de la texture 3D
Private
gTexture As
Long
Ensuite à la fin de la fonction InitScene, on génère la texture :
' Active les textures 3D
glEnable GL_TEXTURE_3D
' Génère un identifiant de texture
glGenTextures 1
, gTexture
' Active cette texture
glBindTexture GL_TEXTURE_3D, gTexture
' Filtrage de la texture (pas de mipmapping => linéaire)
glTexParameteri GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR
glTexParameteri GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR
' Génère les données de la texture de bois
Dim
lRayon As
Single
Dim
lCpt As
Long
Dim
x As
Long
, y As
Long
, z As
Long
' Tableau de données de la texture
Dim
ldata
(
1
To
64
&
*
64
&
*
64
&
*
3
&
) As
Byte
lCpt =
1
For
z =
1
To
64
&
For
y =
1
To
64
&
For
x =
1
To
64
&
' Rayon du point courant
lRayon =
Sqr
(
Abs
((
x -
32
&
) *
(
x -
32
&
) +
(
y -
32
&
) *
(
y -
32
&
)))
' Ajoute un petit décalage en fonction de la profondeur
lRayon =
lRayon +
z /
64
' Si lRayon mod 4 > 1 => couleur claire, sinon couleur foncée
If
(
lRayon Mod
4
>
1
) Then
' Couleur brun clair
ldata
(
lCpt) =
130
'red
ldata
(
lCpt +
1
) =
60
' green
ldata
(
lCpt +
2
) =
10
' blue
Else
' Couleur brun foncé
ldata
(
lCpt) =
100
'red
ldata
(
lCpt +
1
) =
45
' green
ldata
(
lCpt +
2
) =
25
' blue
End
If
' Avance de 3 bytes
lCpt =
lCpt +
3
Next
Next
Next
' Génère la texture
glTexImage3D GL_TEXTURE_3D, 0
, GL_RGB, 64
&
, 64
&
, 64
&
, 0
, GL_RGB, GL_UNSIGNED_BYTE, VarPtr
(
ldata
(
1
))
Le début du code est identique aux textures 2D :
- on active les textures avec la fonction glEnable (on active bien sûr les textures 3D) ;
- on génère un identifiant de texture avec la fonction glGenTextures ;
- on active cette texture avec la fonction glBindTexture ;
- et on définit le filtrage de texture avec la fonction glTexParameteri ; ici on applique un filtrage linéaire.
Ensuite on calcule la couleur de chaque point de la texture.
Chaque point d'une texture 2D était appelé un texel.
Pour une texture 3D, on parle de voxel.
Chaque couleur de voxel est calculée en fonction de sa position x, y et z.
On n'utilise que trois composantes de couleur car la transparence n'est pas utile.
On génère, grâce à un test sur le rayon du point, des cercles marron concentriques pour simuler les nervures du bois.
Pour que la texture ne soit pas trop parfaite, on ajoute un petit décalage en fonction de la profondeur z.
Finalement la texture est générée grâce à la fonction glTexImage3D :
- GL_TEXTURE_3D désigne bien évidemment une texture 3D ;
- GL_RGB désigne le format des données = trois composantes : rouge, vert et bleu ;
- 64&, 64&, 64& est la taille de la texture = un cube de 64 points de côté ;
- GL_UNSIGNED_BYTE désigne le type des données = Byte ;
- Le dernier paramètre désigne l'emplacement des données à utiliser : c'est un pointeur (VarPtr) vers le premier élément du tableau.
VII-D. Application de la texture▲
Pour appliquer la texture au cube, il faut procéder comme pour les textures 2D.
Voici le nouveau code pour dessiner le cube texturé :
' Affecte la texture
glBindTexture GL_TEXTURE_3D, gTexture
' Début de la primitive pour le cube
glBegin GL_QUADS
' Face du haut
Call
glTexCoord3f
(
1
, 1
, 0
): Call
glVertex3f
(
1
, 1
, -
1
)
Call
glTexCoord3f
(
0
, 1
, 0
): Call
glVertex3f
(-
1
, 1
, -
1
)
Call
glTexCoord3f
(
0
, 1
, 1
): Call
glVertex3f
(-
1
, 1
, 1
)
Call
glTexCoord3f
(
1
, 1
, 1
): Call
glVertex3f
(
1
, 1
, 1
)
' Face du bas
Call
glTexCoord3f
(
0
, 0
, 0
): Call
glVertex3f
(-
1
, -
1
, -
1
)
Call
glTexCoord3f
(
1
, 0
, 0
): Call
glVertex3f
(
1
, -
1
, -
1
)
Call
glTexCoord3f
(
1
, 0
, 1
): Call
glVertex3f
(
1
, -
1
, 1
)
Call
glTexCoord3f
(
0
, 0
, 1
): Call
glVertex3f
(-
1
, -
1
, 1
)
' Face de derrière
Call
glTexCoord3f
(
1
, 0
, 0
): Call
glVertex3f
(
1
, -
1
, -
1
)
Call
glTexCoord3f
(
0
, 0
, 0
): Call
glVertex3f
(-
1
, -
1
, -
1
)
Call
glTexCoord3f
(
0
, 1
, 0
): Call
glVertex3f
(-
1
, 1
, -
1
)
Call
glTexCoord3f
(
1
, 1
, 0
): Call
glVertex3f
(
1
, 1
, -
1
)
' Face de devant
Call
glTexCoord3f
(
0
, 0
, 1
): Call
glVertex3f
(-
1
, -
1
, 1
)
Call
glTexCoord3f
(
1
, 0
, 1
): Call
glVertex3f
(
1
, -
1
, 1
)
Call
glTexCoord3f
(
1
, 1
, 1
): Call
glVertex3f
(
1
, 1
, 1
)
Call
glTexCoord3f
(
0
, 1
, 1
): Call
glVertex3f
(-
1
, 1
, 1
)
' Face de gauche
Call
glTexCoord3f
(
0
, 1
, 1
): Call
glVertex3f
(-
1
, 1
, 1
)
Call
glTexCoord3f
(
0
, 1
, 0
): Call
glVertex3f
(-
1
, 1
, -
1
)
Call
glTexCoord3f
(
0
, 0
, 0
): Call
glVertex3f
(-
1
, -
1
, -
1
)
Call
glTexCoord3f
(
0
, 0
, 1
): Call
glVertex3f
(-
1
, -
1
, 1
)
' Face de droite
Call
glTexCoord3f
(
1
, 1
, 0
): Call
glVertex3f
(
1
, 1
, -
1
)
Call
glTexCoord3f
(
1
, 1
, 1
): Call
glVertex3f
(
1
, 1
, 1
)
Call
glTexCoord3f
(
1
, 0
, 1
): Call
glVertex3f
(
1
, -
1
, 1
)
Call
glTexCoord3f
(
1
, 0
, 0
): Call
glVertex3f
(
1
, -
1
, -
1
)
glEnd
' Désactive la texture
glBindTexture GL_TEXTURE_3D, 0
- On active d'abord les textures 3D.
- On active la texture à utiliser (glBindTexture).
- On dessine le cube en donnant des coordonnées de texture.
La principale différence par rapport à une texture 2D est que la fonction glTexCoord3f demande trois paramètres.
Chaque vertex du cube est associé à un voxel de la texture.
Ici l'exemple est simple : on associe chaque sommet du cube à un sommet de la texture 3D.
Et enfin on désactive la texture une fois le dessin terminé.
On obtient alors le résultat attendu :