Initialiser OpenGL avec GLUT

GLUT, quoi qu'est-ce ? Et bien c'est une librairie pour OpenGL (GL utility toolkit) destinée à faciliter la vie du programmeur. Non, elle ne vous fait pas la bouffe ni ne vous torche à votre place, mais elle sait quand même créer une fenêtre dans n'importe quel environnement de n'importe quel OS et bien plus, comme vous le verrez bientôt. Elle a été en fait désignée pour permettre une portabilité à 100% du code. Hé oui ! Vous avez bien lu ! 100% ! Ca veut dire quel que soit l'OS, tous vos programmes OpenGL seront parfaitement compilables sans aucune modifications à apporter ! C'est-y pas génial, ca ?
Mais alors pourquoi j'ai pas commencé par faire un tutorial glut ? Ben d'abord par ce que j'ai appris sans, et qu'ensuite je trouve plus pratique de développer sans glut pour ce qui est du débugage et des test, parce qu'on a beaucoup plus d'options et de trucs comme ça. Mine de rien, ca permet quand même d'appréhender les réactions de chaque machine à OpenGL, de voir les différences entres les cartes 3D etc... Mais glut a lui aussi plein d'avantages : d'abord on peut faire de tout petits programmes tous cons qui tiennent en quelques lignes et peuvent faire des effets excellent, et puis glut ne se contente pas de gérer le graphisme : on peut aussi grâce à glut gérer la souris, le clavier... C'est vraiment excellent !

Après cette brève introduction, passons à la partie code. Je vais moins commenter le code que dans le tutorial sur OpenGL pour win, parce que les remarque sont les mêmes. Donc je vous conseille de lire rapidement le tutorial sus-cité (surtout la 2e partie) afin de saisir les 2 ou 3 concepts de base avant d'aborder celui-ci. Et si vous avez déjà réussi à utiliser OpenGL avec windows, alors ce tutorial-ci sera une partie de plaisir. Dans les #include, on uniquement glut.h. Remarquez qu'ici il n'y a pas de windows.h : c'est un code tout à fait portable. Il n'y a pas non plus gl.h ou glu.h mais ceux-ci sont déjà inclus par glut.h normalement. Mais tout dépend des compilateurs et des systèmes : certains permettent d'inclure les 3, d'autres se contentent de glut.h. Mais pas de panique : toutes les fonctions gl et glu sonnt accessibles dès lors que vous incluez glut.h.

#include <gl/glut.h>

La différence entre les différentes plateformes se fera en fait au moment de la compilation : sous windows, vous incluerez glut32.lib, opengl32.lib et glu32.lib dans vos liens, tandis que sous Unix vous ferez "cc prog.c -o Prog -lX11 -lglut -lGL etc..."
Sous Visual C++, vous n'aurez donc plus à créer un Win32 Apllication Project, avec WinMain et tout le toutim, mais juste un Win32Console Application Project, c'est-à-dire un prog 32 bits qui sait utiliser les dll de win.

Et bien passons maintenant au main() (ahhh, enfin un main normal !), qui va d'ailleurs être plutôt dans le genre

int main( int argc, char *argv[ ], char *envp[ ] )

Si vous n'avez jamais vu cette syntaxe, sachez qu'elle est tout à fait conforme au C ANSI, et qu'elle permet juste de récupérer les arguments de ligne de commande et les variables d'environnement.
Commencons par remplir ce main() avec les fonctions d'initialistation de glut :

int WindowName;
 

int main( int argc, char *argv[ ], char *envp[ ] )

{  
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(640,480); //Optionnel
WindowName = glutCreateWindow("Ma première fenêtre OpenGL !");
glutFullScreen(); //Optionnel
 
return 0;
 
}  
  • glutInit() a besoin des arguments de ligne de commande, donc on lui donne.
  • On transmet à glutInitDisplayMode() les options qu'on veut : ici, j'ai choisi un mode RGBA (32 bits), un double-buffering, et un Z-buffer à titre d'exemple.
  • glutInitWindowSize() et glutInitWindowPos() sont des fonctions qui permettent de spécifier la taille et la postition des fenêtres qui vont être créées.
  • Enfin, on crée notre fenêtre, en transmettant juste le titre, en on récupère un nom unique pour cette fenêtre, qui servira à la redimensionner, la fermer... Donc mieux vaut l'enregistrer en tant que variable globale.

Et là, vous pouvez d'ores et déjà lancer votre programme : ça crée une fenêtre OpenGL en plein écran et tout et tout... et ca la ferme aussitôt ! Hé oui, on a pas encore vu comment gérer les évènements comme on le faisait avec WM_PAINT et toutes ces autres conneries. Et ben on va le faire maintenant : vous vous rapellez qu'à réception du message WM_SIZE, on appelait notre fonction Reshape(), qui remettait les paramètres OpenGL aux goûts de la fenêtre. Et ben là, c'est tout pareil : y'a juste à écrire dans le main() après les quelques initialisations

glutReshapeFunc(Reshape);

Avec notre fonction Reshape() définie de la sorte :

void Reshape(int width, int height)
{  
  glViewport(0,0,width,height);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(
45,
float(width)/float(height),
0.1,
100
);
//Pour les explications, lire le tutorial sur OGL et win
  glMatrixMode(GL_MODELVIEW); //Optionnel
}  

Et de même, on appelait Draw() à réception du message WM_PAINT. Ici, c'est la même chose que pour Reshape() : on crée notre fonction Draw() qui va contenir toutes les fonctions de dessin, et on initialise glut avec

glutDisplayFunc(Draw);

A titre d'exemple, la fonction Draw() peut être quelque chose dans ce genre (référez-vous au tutorial OGL+Windows 2e partie pour toutes les explications sur InitGL(), Draw() et Reshape() ) :

void Draw()
{
} glClear
(
GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT
);
//Efface le frame buffer et le Z-buffer
glMatrixMode(GL_MODELVIEW); //Choisit la matrice MODELVIEW
glLoadIdentity(); //Réinitialise la matrice
gluLookAt(0,0,-10,0,0,0,0,1,0);
glBegin(GL_TRIANGLES);

glVertex2i(0,1);
glVertex2i(-1,0);
glVertex2i(1,0);

glEnd(); //Pour les explications, lire le tutorial sur OGL et win

glutSwapBuffers();

//Attention : pas SwapBuffers(DC) !

glutPostRedisplay();

//Demande de recalculer la scène

Remarquez que cette fonction diffère de la version "sans glut" par glutSwapBuffers(). Donc si vous voyez SwapBuffers(DC) dans les prochains tuts, ne vous étonnez pas et remplacez-le par glutSwapBuffers().
Attention également à glutPostRedisplay() : en effet, Draw() n'est appelée que lorsque glut pense que la fenêtre doit être rafraîchie (donc lorqu'on change de fenêtre, lorsqu'elle est réduite...). Pour demander à glut de refaire le rendu, il faut donc appeler glutPostRedisplay(), sinon votre fenêtre ne sera pas rafraîchie régulièrement.

Ensuite, après avoir initialisé glut, vous pouvez initialiser OpenGL lui-même en vous faisant une petite fonction InitGL contenant tous les trucs nécessaires : glEnable(GL_DEPTH_TEST), glEnable(GL_LIGHTING) etc... Cela ne vous dit peut-être rien pour l'instant, mais vous en aurez besoin plus tard.
Enfin, lancez le gestionnaire glut, qui se chargera de lancer les fonctions Draw() et Reshape() aux moments voulus, grâce à glutMainLoop().

Pour résumer, voici la fonction main() complète :

int main( int argc, char *argv[ ], char *envp[ ] )

{  
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(640,480); //Optionnel
WindowName = glutCreateWindow("Ma première fenêtre OpenGL !");
glutFullScreen(); //Optionnel
 
glutReshapeFunc(Reshape);
glutDisplayFunc(Draw);
InitGL();
 
glutMainLoop();
 
return 0;
 
}  

Ici notre fonction InitGL() ne contient absolument rien, mais nous nous en servirons plus tard. Notez que glutMainLoop() ne s'arrête jamais : on est obligé de sortir du programme par un exit(), ou de fermer la fenêtre manuellement.

Le programme présenté ici donnera quelque chose de ce genre (là c'est sans fullscreen) :

Et voilà, c'est fini ! Vous pouvez maintenant garder cet exemple comme un canevas sur lequel vous n'aurez plus qu'à tisser votre code (c'est beau, non ?). Dans les prochains tutorials, je ferais toujours référence à Draw(), InitGL() et Reshape(), donc vous devrez être censés savoir ce que c'est. En plus, ces fonctions se retrouvent également dans la partie "sans glut" : comme ça je n'aurais pas à expliquer les choses de 2 façons différentes.

Antoche
 


← Initialiser OpenGL avec Windows↑ Tutoriaux OpenGL ↑Les bases →