I. Introduction▲
Au cours de ce tutoriel, nous allons découvrir la programmation de la 3D avec OpenGL.
Cette découverte va se faire en langage VBA ou VB6.
Cependant, les fonctions et techniques utilisées sont les mêmes dans tous les langages.
Pour simplifier, lorsque j'emploie le terme VB, il réfère à VB6 ou à VBA
II. Librairies utilisées▲
Tout d'abord OpenGL est installé avec Windows.
Il y a deux librairies pour OpenGL dans le répertoire système de Windows :
- opengl32.dll : c'est la librairie principale
- glu32.dll = GL Utility : c'est un complément qui contient quelques autres fonctions utiles
OpenGL ne gère pas le fenêtrage : c'est-à-dire qu'il faut fournir à OpenGL une fenêtre sur laquelle il va effectuer le rendu de l'image.
De plus il ne gère pas les entrées clavier, souris, ...
Pour gérer l'affichage des fenêtres et des événements divers (clavier, souris, minuterie, ...), il existe plusieurs librairies.
Glut est une librairie très largement utilisée.
Mais pour une utilisation en VB, je lui ai préféré freeglut qui expose des fonctions similaires, et quelques nouveautés qui nous seront utiles, voir indispensables en VBA.
Nous verrons qu'il est également possible de faire un rendu sur un formulaire sans freeglut.
Enfin pour appeler les fonctions de ces librairies, il faut déclarer chacune d'entre-elles dans VB.
Nous allons donc préparer notre environnement de développement.
III. Le pack de module VB pour OpenGL▲
Tous les modules VB nécessaires à l'utilisation d'OpenGL sont regroupés dans une archive compressée au format zip.
Téléchargez cette archive :
Pack de module VB pour OpengGL
Pour utiliser FreeGlut, téléchargez également la librairie dll :
Librairie FreeGlut
IV. Préparation de l'environnement de développement VB▲
Créez d'abord une nouvelle application Microsoft Office : Access, Excel, Word, ...
.
Ou créez un nouveau projet Visual Basic 6.
Afin de pouvoir utiliser les fonctions OpengGL en VB :
Importez le module standard ModOpenGL_1_1
Ce module contient les déclarations des fonctions et constantes de OpenGL 1.1.
Importez le module standard ModOpenGLTools
Ce module contient les déclarations des fonctions et constantes de OpenGL 1.1 de Glu, ainsi que des fonctions spécifiques à Windows (wgl et gdi32).
Il contient également des fonctions supplémentaires utiles pour l'utisation d'openGL en VB.
Importez le module standard ModOpenGLFreeGlut
Ce module contient toutes les déclarations nécessaires à freeglut.
Pour utiliser FreeGlut (création de fenêtres) :
Placez la librarie freeglut.dll
dans le même répertoire que l'application Office ou le projet VB6.
Cette librairie a été compilée avec Visual C++ Express 2008.
freeglut est sous licence : X-Consortium license.
Avec Office, pour ouvrir l'éditeur VBA, tapez ALT + F11.
Pour importer un module , choisissez dans le menu : Fichier => Importer un fichier ....
V. Première fenêtre avec freeglut▲
Créez un nouveau module standard (Insertion => Module dans Office).
Dans ce module nous ajoutons une fonction FonctionOpenGL dans laquelle nous écrirons le code de création de la fenêtre.
Function
FonctionOpenGL
(
)
End
Function
Pour VB6, créez une procédure Main à la place de cette fonction.
Sub
Main
(
)
End
Sub
Notez qu'on a placé la librairie freeglut.dll dans le même répertoire que l'application.
Pour appeler les fonctions de cette librairie, il faut donc d'abord la charger.
Si on avait placé cette librairie dans le répertoire système de Windows, il n'aurait pas été nécessaire de la charger.
Pour charger la librairie, utilisons la fonction LoadLibrary (elle est déclarée dans le module ModFreeGlut).
'
Chargement
de
freeglut
If
LoadLibrary
(
CurrentProject.
Path
&
"
\freeglut.dll
"
) =
0
Then
MsgBox
"
Impossible
de
charger
la
librairie
freeglut
"
Exit
Function
End
If
Si le programme n'arrive pas à charger la librairie, la fonction renvoie 0 et on affiche alors un message d'erreur.
Remplacez CurrentProject en fonction de l'application utilisée :
- CurrentProject pour Access.
- ThisWorkBook pour Excel.
- ThisDocument pour Word.
- App pour VB6.
On peut maintenant appeler les fonctions de freeglut.
Première étape : l'initialisation :
'
Initialisation
de
la
librairie
glutInit 0
&
, "
"
D'après la documention de glutInit, les paramètres de cette fonction d'initialisation sont utilisés pour les systèmes X Window.
Nous n'utilisons pas ces paramètres, on passe donc des valeurs vides.
Deuxième étape : l'initialisation du mode d'affichage :
'
Initialisation
du
mode
d'affichage
glutInitDisplayMode GLUT_RGBA Or
GLUT_DOUBLE Or
GLUT_DEPTH
- GLUT_RGBA signifie que la fenêtre utilise le modèle de couleur RGB (rouge, vert, bleu) plus une composante alpha de transparence.
- GLUT_DOUBLE signifie que nous souhaitons utiliser un double buffer (nous le détaillerons plus tard).
- GLUT_DEPTH signifie que nous souhaitons utiliser un tampon de profondeur (nous l'utiliserons également plus tard).
Troisème étape : création d'une fenêtre :
'
Création
d'une
fenêtre
glutCreateWindow "
Tutoriel
fenêtre
GLUT
"
Le titre de la fenêtre est passé en paramètre.
Cette fonction renvoie un numéro de fenêtre (interne à freeglut) que l'on peut utiliser ensuite pour, par exemple, redimensionner, positionner ou détruire la fenêtre.
Il est également possible de créer plusieurs fenêtres et de passer de l'une à l'autre.
Nous n'utiliserons pas ce numéro.
Quatrième étape : Exécution de la boucle principale :
Glut fonctionne avec une boucle principale qu'il est nécessaire d'exécuter.
'
Boucle
principale
glutMainLoop
Cette boucle est sans fin, les instructions situées après l'appel à cette fonction ne seront pas exécutées tout de suite.
En VBA avec Office :
Si on exécute la fonction FonctionOpenGL (touche F5), on voit bien la fenêtre s'afficher mais si on la ferme toute l'application se ferme brutalement.
Pour éviter ce comportement, on définit une option de freeglut très pratique :
Ajoutez cette instruction juste après l'initialisation avec glutInitDisplayMode.
'
Définition
de
l'option
de
sortie
de
boucle
glutSetOption GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS
Cette option demande à freeglut de continuer l'exécution après l'instruction glutMainLoop au lieu d'arrêter l'application.
On pourra alors si besoin fermer nous-mêmes l'application correctement.
Testons à nouveau notre programme, on peut fermer la fenêtre tout en conservant l'application ouverte.
Mais rien ne s'affiche dans la fenêtre, ou plutôt si : la fenêtre contient ce qui se situe dessous lors de son ouverture.
Pour l'instant c'est normal, on n'a pas encore géré l'affichage du contenu de notre fenêtre.
Cinquième étape : la fonction d'affichage :
On peut avec freeglut définir des fonctions de rappel (CallBack en anglais).
Ces fonctions sont exécutées depuis freeglut au cours de la boucle que nous avons exécutée avec glutMainLoop.
La liste des fonctions et de leur déclaration en VB est décrite dans le chapitre suivant.
La fonction de rappel indispensable est la fonction d'affichage.
Cette fonction est appelée à chaque fois qu'il est nécessaire d'afficher le contenu de la fenêtre.
Créez la fonction d'affichage dans le module VB :
'
Fonction
d'affichage
Public
Sub
CallBackDraw
(
)
End
Sub
Puis définissez la fonction dans freeglut, avant l'appel à glutMainLoop.
'
Fonction
d'affichage
glutDisplayFunc AddressOf CallBackDraw
Dans la fonction d'affichage on va :
- Vider les buffers avec glClear.
- Réaliser les opérations de rendu (dessin d'obets, éclairage, ...), ce que nous ajouterons par la suite.
- Echanger les buffers pour afficher le résultat dans la fenêtre.
'
Fonction
d'affichage
Public
Sub
CallBackDraw
(
)
'
Vide
les
buffers
couleur
et
profondeur
glClear GL_COLOR_BUFFER_BIT Or
GL_DEPTH_BUFFER_BIT
'
Echange
les
buffers
glutSwapBuffers
End
Sub
Vous verrez sans doute dans diverses documentations un appel à glFlush qui demande à OpengGL d'exécuter les commandes en attente.
Nous n'appelons pas cette fonction ici, glutSwapBuffers le fait pour nous.
Notez également la fonction utilisée : glutSwapBuffers et non pas SwapBuffers.
Voici le rappel du code complet de notre première fenêtre GLUT :
Option
Explicit
Function
FonctionOpenGL
(
)
'
Chargement
de
freeglut
If
LoadLibrary
(
CurrentProject.
Path
&
"
\freeglut.dll
"
) =
0
Then
MsgBox
"
Impossible
de
charger
la
librairie
freeglut
"
Exit
Function
End
If
'
Initialisation
de
la
librairie
glutInit 0
&
, "
"
'
Initialisation
du
mode
d'affichage
glutInitDisplayMode GLUT_RGBA Or
GLUT_DOUBLE Or
GLUT_DEPTH
'
Création
d'une
fenêtre
glutCreateWindow "
Tutoriel
fenêtre
GLUT
"
'
Définition
de
l'option
de
sortie
de
boucle
glutSetOption GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS
'
Fonction
d'affichage
glutDisplayFunc AddressOf CallBackDraw
'
Boucle
principale
glutMainLoop
End
Function
'
Fonction
d'affichage
Public
Sub
CallBackDraw
(
)
'
Vide
les
buffers
couleur
et
profondeur
glClear GL_COLOR_BUFFER_BIT Or
GL_DEPTH_BUFFER_BIT
'
Echange
les
buffers
glutSwapBuffers
End
Sub
Exécutez (F5) la fonction FonctionOpenGL pour afficher la fenêtre, qui est uniquement un fond noir pour l'instant.
- Notez que le buffer de couleurs est initialisé avec la couleur définie par glClearColor.
glClearColor 1, 0, 0, 1 par exemple définit une couleur de fond rouge.
- Le buffer de profondeur est vidé en donnant à chaque pixel une profondeur de 1.
Ceci peut être changé avec la fonction glClearDepth.
VI. Les fonctions de rappel de freeglut▲
On peut avec freeglut définir des fonctions de rappel (CallBack en anglais).
Ces fonctions sont exécutées depuis freeglut au cours de la boucle que nous avons exécutée avec glutMainLoop.
Fonction freeglut | Description | Déclaration VB |
---|---|---|
glutDisplayFunc AddressOf CallBackDraw | Appelée lorsqu'un affichage de la fenêtre est nécessaire. | Public Sub CallBackDraw() |
glutIdleFunc AddressOf CallBackIdle | Appelée constamment lorsque le programme n'a pas d'événements à traiter dans sa pile. | Public Sub CallBackIdle() |
glutReshapeFunc AddressOf CallBackReshape | Appelée lorsque la fenêtre est redimensionnée. | Public Sub CallBackReshape(ByVal width As Long, ByVal height As Long) |
glutKeyboardFunc AddressOf CallBackKeyBoard | Appelée lorsqu'une touche est appuyée. - char est le code ASCII du caractère. - x et y sont les coordonnées de la souris. |
Public Sub CallBackKeyBoard(ByVal char As Byte, ByVal x As Long, ByVal y As Long) |
glutKeyboardUpFunc AddressOf CallBackKeyBoardUp | Appelée lorsqu'une touche est relâchée. - char est le code ASCII du caractère. - x et y sont les coordonnées de la souris. |
Public Sub CallBackKeyBoardUp(ByVal char As Byte, ByVal x As Long, ByVal y As Long) |
glutCloseFunc AddressOf CallBackClose | Appelée lorsque la fenêtre est fermée. | Public Sub CallBackClose() |
glutSpecialFunc AddressOf CallBackSpecial | Appelée lorsqu'une touche spéciale est appuyée. - key est le code de la touche. - x et y sont les coordonnées de la souris. Retrouvez les valeurs possibles de key dans le module ModFreeGlut. Ce sont les constantes qui commencent par GLUT_KEY_ |
Public Sub CallBackSpecial(ByVal key As Long, ByVal x As Long, ByVal y As Long |
glutSpecialUpFunc AddressOf CallBackSpecialUp | Appelée lorsqu'une touche spéciale est relâchée. - key est le code de la touche. - x et y sont les coordonnées de la souris. Retrouvez les valeurs possibles de key dans le module ModFreeGlut. Ce sont les constantes qui commencent par GLUT_KEY_ |
Public Sub CallBackSpecialUp(ByVal key As Long, ByVal x As Long, ByVal y As Long |
glutMouseFunc AddressOf CallBackMouse | Appelée lorsqu'un bouton de la souris change d'état. - button est le code du bouton. - state est l'état du bouton. - x et y sont les coordonnées de la souris. - button prend les valeurs : GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON ou GLUT_RIGHT_BUTTON. - state prend les valeurs : GLUT_DOWN ou GLUT_UP. |
Public Sub CallBackMouse(ByVal button As Long, ByVal state As Long, ByVal x As Long, ByVal y As Long) |
glutMouseWheelFunc AddressOf CallBackMouseWheel | Appelée lorsqu'on déplace la molette de la souris. - wheel est le numéro de la molette. - direction est la direction dans laquelle on l'a déplacée : -1 ou 1. - x et y sont les coordonnées de la souris. |
Public Sub CallBackMouseWheel(ByVal wheel As Long, ByVal direction As Long, ByVal x As Long, ByVal y As Long) |
glutMotionFunc AddressOf CallBackMotion | Appelée lorsqu'on déplace la souris avec un bouton appuyé. - x et y sont les coordonnées de la souris. |
Public Sub CallBackMotion(ByVal x As Long, ByVal y As Long) |
glutPassiveMotionFunc AddressOf CallBackPassiveMotion | Appelée lorsqu'on déplace la souris et qu'aucun bouton n'est appuyé. - x et y sont les coordonnées de la souris. |
Public Sub CallBackPassiveMotion(ByVal x As Long, ByVal y As Long) |
glutJoystickFunc AddressOf CallBackJoystick, n | CallBackJoystick sera appelée toutes les n millisecondes. - buttonMask contient les boutons appuyés. - x, y et z la valeur de déplacement du joystick sur chacun de ces axes. |
Public Sub CallBackJoystick(ByVal buttonMask As Long, ByVal x As Long, ByVal y As Long, ByVal z As Long) |
glutTimerFunc n, AddressOf CallBackTimer, val | CallBackTimer sera appelée n millisecondes plus tard. - val contient une valeur utilisateur. La fonction de rappel n'est appelée qu'une seule fois. Il faut la relancer si on veut un timer en permanence. |
Public Sub CallBackTimer(ByVal val As Long) |