L’affichage : Projection et Transformations
publié le jeudi 19 octobre 2006 (vu 1849 fois)

Comme vous le savez déjà, OpenGL est une bibliothèque d’affichage en 3 dimensions. L’écran sur lequel vous voulez afficher des objets en 3 dimensions est quand à lui en 2 dimensions. Comment OpenGL fait-il dans ce cas ?

Pour transformer les coordonnées 3D des polygones qu’on lui envoie, OpenGL utilise des matrices. L’une de ces matrices est appelée Matrice de Projection car elle “projette” une coordonnée 3D pour obtenir une coordonnée 2D en relation avec l’écran où l’affichage doit se faire. La projection se fera donc en fonction des paramètres qui sont stockés dans la Matrice de Projection.

OpenGL doit aussi connaitre la position et la taille de la surface d’affichage
Le schéma ci-dessus montre l’exemple d’une projection en perspective : Projection en perspective

Le cube en 3D (en vert) est transformé en 2D pour être affiché sur l’écran (en rouge) grâce à la Matrice de Projection. La matrice de projection définit une transformation basée sur un point de fuite (le point O), comme le font les peintres, afin de créer un effet de perspective et par conséquent l’impression d’une 3ème dimension.


Avant de nous lancer dans la configuration de notre affichage, revenons un peu sur notre application de base (voir Introduction à OpenGL : la SDL) afin d’y apporter quelques modifications. Commençons par modifier notre programme en remplaçant la partie suivante :

par un appel à une fonction d’initialisation :

De même, remplaçons le simple nettoyage de l’écran :

par un appel à une fonction de dessin :

Commençons maintenant par créer cette fonction d’initialisation qui va d’abord initialiser la SDL comme c’était le cas avant dans le main et retournera un booléen en cas d’erreur :

Vous remarquerez la fonction SDL_WM_SetCaption que j’ai ajoutée après la création de la fenêtre. Elle permet simplement, comme le suggère le commentaire, de changer le titre de la fenêtre via le premier paramètre et, éventuellement, de lui atttribuer un autre titre lorsque l’application est « icônifiée » en passant un autre nom en second paramètre.

Continuons notre initialisation avec quelques réglages OpenGL. Nous pouvons par exemple spécifier la couleur avec laquelle l’affichage doit être effacé avec la fonction glClearColor qui demande les 4 composantes de la couleur en paramètre (rouge, vert, bleu et transparence :

Note : La transparence définie ici n’est pas la transparence de la fenêtre mais une information permettant de traiter des effets de transparence que nous verrons plus tard.

Vient la configuration de l’affichage. OpenGL est déjà au courant que l’affichage se fait dans la fenêtre, mais il faut lui indiquer le plan de projection (l’écran) en termes de position et de taille. Cela se fait à l’aide de la fonction glViewport. Les paramètres à passer sont les coordonnées X et Y du coin inférieur droit où commence la zone d’affichage ainsi que la largeur et la hauteur en pixels de cette zone. En ce qui nous concerne évitons les complications, nous allons utiliser toute la surface disponible dans notre fenêtre :

Attelons nous maintenant à configurer la projection. Pour commencer il faut sélectionner la matrice de projection utilisée par OpenGL pour ses transformations. Pour ce faire, nous faisons appel à la fonction glMatrixMode avec comme paramètre la définition de la matrice de projection qui est... GL_PROJECTION, facile non ? ^^

Réinitialiser une matrice consiste non pas à la remplir de 0 ou de 1 mais à en faire une matrice identité. Pour réinitialiser une matrice, rien de plus simple. Il suffit d’appeler la fonction glLoadIdentity qui chargera la matrice identité dans la matrice courante qui, dans notre cas, est la matrice de projection que nous avons précédemment sélectionnée :

Vient ensuite la configuration de la transformation en elle même. Une matrice identité, par définition, n’effectue aucune transformation. Hors notre matrice de projection doit transformer les coordonnées 3D en coordonnées 2D pour notre écran. Pour cela, nous allons faire appel à une fonction de la glu (GL Utilities), la bibliothèque d’utilitaires complémentaire à OpenGL. Là où les fonctions OpenGL sont nommées avec le préfixe « gl », les fonctions de la glu ont toutes le préfixe « glu ». La fonction gluPerspective permet de configurer la projection en mode perspective (comme son nom l’indique plus ou moins ;-p). Concrêtement, la fonction multiplie la matrice de projection par une matrice générée à l’aide des paramètres qui lui sont passés. Ces paramètres sont 4 valeurs de type GLdouble qui indiquent dans l’ordre :
- l’angle de vision vertical en degré
- le rapport d’aspect du champ de vision
- la distance du plan de coupe proche
- la distance du plan de coupe lointain Ce qui donne :

Il nous reste à sélectionner la matrice de transformations qui va appliquer les modifications à nos coordonnées avant leur projection. Les modifications en question sont les translations, rotations et autres mises à l’échelle. La sélection de la matrice se fera comme précédemment avec glMatrixMode qui prendra cette fois le paramètre GL_MODELVIEW :

ainsi, OpenGL est en mode transformations et prêt à recevoir les ordres pour dessiner.

Nous avons terminé notre initialisation. Notre fonction qui doit retourner un booléen pour indiquer que tout s’est bien passé va donc se clore le plus simplement du monde :


Pour terminer, nous allons préparer la fonction de dessin pour son usage ultérieur. Commençons donc par sa déclaration :

La première chose à faire avant de dessiner, c’est d’effacer le contenu de la fenêtre :

Exactement comme le faisait notre précédent programme.

La fonction d’initialisation a laissé la matrice en mode transformations, et comme pour la matrice de projection, il faut faire une mise à zéro avant toute manipulation ou transfert de coordonnées. La fonction glLoadIdentity qui nous a servi pour réinitialiser la matrice de projection servira cette fois à (ré)initialiser la matrice de transformations :

En réinitialisant la matrice de transformation, le point de vue se situe à l’origine (coordonnées {0,0,0} respectivement x,y et z).


Nous allons nous arrêter ici pour ce qui est de cette partie. Vous remarquerez qu’au point où il en est, ce dernier ne fait rien de plus que le précédent. Il initialise l’affichage pour la fenêtre que nous avions créée mais, comme il n’affiche toujours rien, on ne voit pas la différence. Une fenêtre vide n’étant pas des plus intéressantes, il serait temps de passer à quelque chose de plus concret. Rendez-vous au prochain article ;-)

Code Source (fichier Zip de 1.2 ko)
Executable windows (fichier Zip de 2.4 ko)