Préparer une fenêtre Windows à recevoir OpenGL

 

Bon je ne vais pas refaire un cours sur le développement en C de fenêtres Windows. Voyez le chapitre développement en C de Windows, si quelque chose n'est pas claire. Il est en effet plus fréquent sous Windows d'utiliser les commandes de création de fenêtres en utilisant les bibliothèques de Microsoft.

Il existe cependant une autre solution, qui se nomme GLUT. GLUT est une librairie d'OpenGL permettant de se créer très facilement des fenêtres sous Windows (mais aussi sous d'autres systèmes comme Linux. Rendant votre code un peu plus portable, du moins pour la partie gestion des fenêtres). Donc si vous ne connaissez rien à Windows et que vous n'avez pas envie de "perdre" votre temps à comprendre comment cela marche, mais êtes plutôt intéressé par OpenGL, vous pouvez vous rendre dans la section OpenGL sous Linux, où j'utilise GLUT pour expliquer tout OpenGL ! Sachant que GLUT peut s'apprendre très très rapidement !

 

Cependant, pour le développement sous Windows, il n'est pas non plus nécessaire de tout comprendre à Windows, du moins dans un premier temps. La seule chose importante à savoir est:

Sous Windows, dans une application fenêtrée (Voir les bases), il faut créer une procédure WinMain() et non main()...

 

OpenGL ne fait rien du tout au niveau hardware, il se contente donc de préparer une image (render). Au système de faire l'affichage. D'où comment créer une fenêtre Windows: Il s'agit de créer une classe de fenêtre qui sera instanciée. Il faut savoir développer procédure de gestion des messages.

Pour dessiner dans une fenêtre sous Windows, il est nécessaire d'avoir un contexte de périphérique. Il faudra donc s'attendre à passer à OpenGL ce handle à un moment ou un autre. Seule différence par rapport à ce qui peut-être fait dans une fenêtre classique, ici OpenGL utilisera toujours le même contexte de périphérique durant toute la durée de vie du programme.

Pour récupérer un contexte de périphérique, il faut agir lors de la réception du message WM_CREATE dans la procédure de gestion des messages de notre fenêtre (GetDC()). Et libérer ce contexte (ReleaseDC()) à la destruction de la fenêtre (lors de la réception du message WM_CLOSE).

 

La petite différence avec le développement standard d'une fenêtre sous Windows se verra surtout au niveau de la gestion des messages.

En effet, il ne s'agira certainement pas de faire un simple rendu d'une image, mais généralement de faire une animation compléte en 2D ou 3D. Il ne faut donc pas attendre "bêtement" après un message qui risque de ne pas arriver. Car l'animation ne serait alors pas bien terrible et même saccader. Une solution parmis tant d'autres sera de faire ceci :


Vous noterez que ce code ressemble fort à celui de l'exemple fourni avec DEV-C++ (il faut dire qu'il n'y a pas trente mille solutions !), mais il existe quelques variantes qui marchent tout aussi bien.

Par exemple, ne pas retirer le message dans la file de messages, mais utiliser alors un GetMessage (qui retirera ce message) et en contrôlant sa valeur de retour pour mettre fin à la boucle...

Ou encore ne pas mettre de else sur le if (PeekMessage()...) pour systèmatiquement effectuer les opérations de 3D.

Voilà, nous avons préparé une fenêtre pour utiliser OpenGL. Reste maintenant à initialiser OpenGL, à l'utiliser et à la détruire en fin de vie du programme !

 

Enfin, il peut être intéressant d'intercepter le message WM_ERASEBKGND. Ce message est envoyé lorsqu'il faut effacer la zone cliente (par exemple lorsque l'on retaille la fenêtre...). Or, c'est normalement à OpenGL de s'occuper du rendu dans la zone cliente, il vaut donc mieux que Windows n'interfére pas dans l'affichage ! Sinon, vous risquez d'avoir comme des flash à l'écran !

Ce problème pourra être résolu en mettant dans la procédure de gestion des messages:

case WM_ERASEBKGND:
return 0;

Image non trouvée !Si vous ne voulez pas conserver le contexte de périphérique contrairement à ce que je vous ai proposé de faire, certains drivers OpenGL semblent se planter sur le contexte de périphérique. Ils n'aimeraient pas ce changement de contexte. Une solution existe pour remédier à cela: Il suffit d'ajouter le style CS_OWNDC de la classe de la fenêtre. Ce style va en effet forcer Windows à conserver le contexte de périphérique pour chacunes des fenêtres qui seront créées avec cette classe. Remarque: Vous n'avez alors pas à demander sans arrêt le handle sur le contexte de périphérique. Une seule fois suffira.

Je n'ai personnellement pas ce problème, je n'ai donc pas positionné ce style dans mes exemples.