Cours Complet sur OpenGL par Eric Bittard
Cours Complet sur OpenGL par Eric Bittard
Open GL
Cours composé par Eric Bittar, d'après le livre The OpenGL Programming Guide Mason Woo, OpenGL
Architectural Review Board, Jackie Neider, Tom Davis, Dave Shreiner. ISBN 0201604582
1
I. Présentation générale .............................................................................................................................................................2
Pipe-Line de Rendu simplifié ..........................................................................................................................................................2
Les Bibliothèques co-existant avec OpenGL ..................................................................................................................................2
Utilisation de GLUT........................................................................................................................................................................2
Les primitives géométriques............................................................................................................................................................3
Les couleurs.....................................................................................................................................................................................4
Le vecteur normal en un point.........................................................................................................................................................4
Le modèle d'ombrage ......................................................................................................................................................................4
II. Vision.....................................................................................................................................................................................5
Principe de la vision ........................................................................................................................................................................5
La transformation de modélisation ..................................................................................................................................................5
La transformation de vision.............................................................................................................................................................6
La transformation de projection ......................................................................................................................................................7
La transformation du viewport ........................................................................................................................................................7
Compréhension par l'exemple .........................................................................................................................................................8
Exercice...........................................................................................................................................................................................8
Modélisation hiérarchique ...............................................................................................................................................................9
Description hiérarchique d'une scène ..............................................................................................................................................9
Pile de transformations ..................................................................................................................................................................10
Manipulation des matrices de transformation................................................................................................................................10
Exercices .......................................................................................................................................................................................10
I. Présentation générale
OpenGL est un système graphique qui permet de visualiser une scène 3D (et aussi 2D). Les objets de cette
scène peuvent être composés de points, de lignes, de polygones, de quadriques, de nurbs. Ils possèdent des
attributs graphiques : paramètres de réflexion, couleur, texture. L'éclairage de la scène est réalisé par des
lumières de différents types (spot, lumière à l'infini).
La bibliothèque OpenGL a été crée par Silicon Graphics et bénéficie sur ces machines de l'accélération
matérielle. On trouve de plus en plus de cartes 3D grand public qui implémentent les instructions OpenGL.
Une implémentation logicielle libre de droits d'OpenGL très performante a été écrite par Brian Paul : Mesa.
C'est cette implémentation que nous utiliserons. Elle a l'avantage d'utiliser l'accélération des cartes
graphiques 3dfx sous Linux.
Utilisation de GLUT
Pour la compilation, copiez le Makefile et tapez make lin
• Examinez et compilez le programme hello.c Comprenez l'utilité des différentes procédures.
• faites de même pour double.c.
Les fonctions de gestion d'une fenêtre
• glutInit(int * argc, char **argv) initialise GLUT et traite les arguments de la ligne de commande.
Les couleurs
La couleur d'un objet est spécifiée par l'appel à glColor(...).
Le modèle d'ombrage
Chaque facette d'un objet peut être affichée d'une unique couleur (ombrage plat) ou à l'aide de plusieurs
couleurs (ombrage lissé). OpenGL implémente une technique de lissage appelée Ombrage de Gouraud. Ce
choix s'effectue avec glShadeModel(GLenum mode).
Compilez scene.c et exécutez le programme obtenu. Changez de mode de rendu avec les touches 's' et 'S'.
II. Vision
Principe de la vision
Le processus de transformation qui produit une image à partir d'un modèle de scène 3D est analogue à celui
qui permet d'obtenir une photographie d'une scène réelle à l'aide d'un appareil photo. Il comprend quatre
étapes :
Avec un appareil photo Avec un ordinateur type de transformation
1 Positionner l'appareil photo Placer la caméra virtuelle transformation de vision
Arranger les éléments d'une scène à Composer une scène virtuelle à
2 transformation de modélisation
photographier représenter
3 Choisir la focale de l'appareil photo choisir une projection transformation de projection
Choisir la taille de la photographie au choisir les caractéristiques de
4 transformation du viewport
développement l'image
[Matrice de
[Matrice de [Division [Transformation
[Sommets] - Modélisation- - - - -
Projection] perspective] du viewport]
Vision]
Coordonnées
Coordonnées
Coordonnées
Coordonnées
de la fenêtre
normalisées
de clipping
de l'oeil
La transformation de modélisation
La manipulation d'objets 3D peut mener à des réflexions complexes pour bien positionner et orienter les
objets. En effet, l'application successive d'une translation puis d'une rotation, ou l'inverse mènent à des
résultats différents.
Pour s'y retrouver, il suffit de se dire que la transformation est appliquée au repère local de l'objet.
La transformation de vision
Elle modifie la position et l'orientation de la caméra virtuelle.
La position par défaut de la caméra est à l'origine du repère de la scène, orientée vers les z négatifs, et la
verticale de la caméra est alignée avec l'axe des y positifs :
En fait, ce qui compte pour la visualisation est la position relative de la caméra par rapport aux objets. Il est
équivalent par exemple de translater la caméra d'un vecteur T ou de translater tous les objets du vecteur -T.
On utilise ainsi les procédures OpenGL de translation et de rotation appliquées aux objets, glTranslate*() et
glRotate*() pour changer le point de vue de la caméra.
On peut également utiliser (et c'est plus simple pour commencer ) la procédure gluLookAt(GLdouble
eyex,GLdouble eyey, GLdouble eyez, GLdouble centerx,GLdouble centery,GLdouble centerz, GLdouble
upx, GLdouble upy, GLdouble upz ).
La transformation de projection
N'oubliez pas d'abord d'écrire glMatrixMode(GL_PROJECTION);glLoadIdentity(); avant les commandes
de transformation.
Projection perspective
• glFrustum() ou gluPerspective() peuvent être utilisées.
Projection orthographique
• glOrtho() sera utilisée.
Clipping
• Les 6 plans de définition du volume de vision sont des plans de clipping : toutes les primitives qui se
trouvent en dehors de ce volume sont supprimées.
La transformation du viewport
• glViewport(GLint x, GLint y, GLint largeur, GLint hauteur) sera utilisée pour définir une zone
rectangulaire de pixels dans la fenêtre dans laquelle l'image finale sera affichée. Par défaut, les
valeurs initiales du viewport sont (0,0, largeurFenêtre, hauteurFenêtre)
Exercice
• Créez une image d'une scène comprenant une sphère rouge de rayon unité en (2,0,0),
(glutSolidSphere(GLdouble radius, GLint slices, GLint stacks)), un cube bleu d'arête 2, tourné de
20° autour de l'axe x du repère de toute la scène, positionné en (0,3,0), et un cube jaune tourné de -
20° autour de l'axe z du repère de la scène, positionné en (3,3,3) (glutSolidCube(GLdouble size).
Positionnez la caméra de manière à voir l'ensemble des objets.
• Quelle difficulté éprouvez-vous ?
Modélisation hiérarchique
Description hiérarchique d'une scène
Définition
• Un modèle hiérarchique permet de décrire facilement des objets complexes composés d'objets
simples. La scène est organisée dans un arbre tel que les objets ne sont plus définis par leur
transformation absolue par rapport au repère de toute la scène, mais par leur transformation relative
dans cet arbre.
• Comme un même objet peut être inclus plusieurs fois dans la hiérarchie, la structure de données est
un Graphe Orienté Acyclique (DAG)
• A chaque noeud est associé un repère. Le repère associé à la racine est le repère de la scène.
• A chaque arc est associé une transformation géométrique qui positionne l'objet fils dans le repère de
son père.
Construction
La structure hiérarchique du modèle peut être induite par :
• Un processus de construction ascendant ("bottom-up")
dans lequel les composants de base (primitives géométriques) sont utilisés comme des blocs
de construction et assemblés pour créer des entitées de niveau plus élevé, et ainsi de suite.
• Un processus de construction descendant ("top-down")
Dans lequel on effectue une décomposition récursive d'un modèle géométrique en objets plus
simples jusqu'à aboutir à des objets élémentaires (primitives géométriques)
Exemple
Pile de transformations
OpenGL utilise les coordonnées homogènes pour manipuler ses objets (cf Cours de Math). Il maintient trois
matrices 4x4 distinctes pour contenir les différentes transformations.
Pour coder l'arbre de description de la scène, il faut utiliser la pile de transformation, en empilant la matrice
de transformation courante (sauvegarde des caractéristiques du repère local associé) avant de descendre dans
chaque noeud de l'arbre, et en dépilant la matrice en remontant (récupération du repère local associé).
• glPushMatrix() Empile la matrice courante pour sauvegarder la transformation courante.
• glPopMatrix() Dépile la matrice courante (La matrice du haut de la pile est supprimée de la pile, et
elle devient la matrice courante)
Exercices
• Copiez le programme robot.c et compilez-le chez vous.
• Faites le dessin du graphe de la scène avec toutes les transformations.
• Faites un schéma du bras du robot en indiquant les repères locaux de l'épaule (shoulder) et du
coude (elbow)
• Modifiez la scène en ajoutant deux doigts (en opposition) au bras du robot, chaque doigt étant
composé de deux segments. Faites le dessin du nouveau graphe, et le schéma du bras
complet.
• Modifiez le programme en conséquent. Chaque élément doit être mobile de manière
indépendante et doit être animable par l'utilisateur au travers du clavier.
Ajoutez un degré de rotation du poignet : suivant l'axe du bras.
III. Eclairage
Modèle d'éclairage OpenGL
La perception de la couleur de la surface d'un objet du monde réel dépend de la distribution de l'énergie
des photons qui partent de cette surface et qui arrivent aux cellules de la rétine de l'œil. Chaque objet
réagit à la lumière en fonction des propriétés matérielles de sa surface.
Le modèle d'éclairage d'OpenGL considère qu'un objet peut émettre une lumière propre, renvoyer dans
toutes les directions la lumière qu'il reçoit, ou réfléchir une partie de la lumière dans une direction
particulière, comme un miroir ou une surface brillante.
Les lampes, elles, vont envoyer une lumière dont les caractéristiques seront décrites par leurs trois
composantes : ambiante, diffuse ou spéculaire.
OpenGL distingue quatre types de lumières :
Lumière émise
Ne concerne que les objets
Les objets peuvent émettre une lumière propre, qui augmentera leur intensité, mais n'affectera pas les
autres objets de la scène.
Lumière ambiante
Concerne les objets et les lampes
C'est la lumière qui a tellement été dispersée et renvoyée par l'environnement qu'il est impossible de
déterminer la direction d'où elle émane. Elle semble venir de toutes les directions. Quand une lumière
ambiante rencontre une surface, elle est renvoyée dans toutes les directions.
Lumière diffuse
Concerne les objets et les lampes
C'est la lumière qui vient d'une direction particulière, et qui va être plus brillante si elle arrive
perpendiculairement à la surface que si elle est rasante. Par contre, après avoir rencontré la surface, elle
est renvoyée uniformément dans toutes les directions.
Lumière spéculaire
Concerne les objets et les lampes
La lumière spéculaire vient d'une direction particulière et est renvoyée par la surface dans une direction
particulière. Par exemple un rayon laser réfléchi par un miroir.
Brillance
Ne concerne que les objets
Cette valeur entre 0.0 et 128.0 détermine la taille et l'intensité de la tâche de réflexion spéculaire. Plus la
valeur est grande, et plus la taille est petite et l'intensité importante.
Les lampes
Nombre de lampes
OpenGL offre d'une part une lampe qui génère uniquement une lumière ambiante (lampe d'ambiance), et
d'autre part au moins 8 lampes (GL_LIGHT0, ... , GL_LIGHT7) que l'on peut placer dans la scène et
dont on peut spécifier toutes les composantes.
La lampe GL_LIGHT0 a par défaut une couleur blanche, les autres sont noires par défaut.
La lampe GL_LIGHTi est allumée par un glEnable(GL_LIGHTi)
Il faut également placer l'instruction glEnable(GL_LIGHTING) pour indiquer à OpenGL qu'il devra
prendre en compte l'éclairage.
Couleur des lampes
Dans le modèle d'OpenGL, la couleur d'une composante de lumière d'une lampe est définie par les
pourcentages de couleur rouge, verte, bleue qu'elle émet.
Par exemple voici une lampe qui génère une lumière ambiante bleue :
Lampes directionnelles
Il s'agit d'une lumière qui vient de l'infini avec une direction particulière.
La direction est spécifiée par un vecteur (x,y,z)
GLfloat direction[4];
direction[0]=x; direction[1]=y; direction[2]=z;
direction[3]=0.0; /* notez le zéro ici */
glLightfv(GL_LIGHT0, GL_POSITION, direction);
Lampes positionnelles
La lampe se situe dans la scène au point de coordonnées (x,y,z)
GLfloat position[4];
position[0]=x; position[1]=y; position[2]=z;
position[3]=1.0; /* notez le un ici */
glLightfv(GL_LIGHT0, GL_POSITION, position);
Modèle d'éclairage
Il faut indiquer avec glLightModel*() si les calculs d'éclairage se font de la même façon ou non sur
l'envers et l'endroit des faces des objets.
Il faut également indiquer si OpenGL doit considérer pour ses calculs d'éclairage que l'œil est à l'infini
ou dans la scène. Dans ce dernier cas, il faut calculer l'angle entre le point de vue et chacun des objets,
alors que dans le premier cas, cet angle est ignoré ce qui est moins réaliste, mais moins coûteux en
27/09/03 Page 12/19
Eric Bittard Cours OpenGL
Transparence
La transparence est obtenue en indiquant pour un objet une couleur diffuse RVBA ou la valeur A sur
le canal alpha est strictement plus petite que un.
Exercice 1
4. Copiez et compilez le programme colormat.c. Il permet de modifier indépendamment les
quatre composants du matériau de la sphère.
5. Ajoutez une lampe en (-1,1,1) qui émet une lumière ambiante verte, une lumière diffuse
bleue, et une lumière spéculaire rouge.
Utilisez les touches '0' (resp. '1') pour allumer et éteindre la lampe 0 (resp. 1).
Listes d'affichage
Il s'agit d'un mécanisme pour stocker des commandes OpenGL pour une exécution ultérieure, qui est
utile pour dessiner rapidement un même objet à différents endroits.
Les instructions pour stocker les éléments d'une liste d'affichage sont regroupées entre une instruction
glNewList(GLuint numList, GLenum mode ) et une instruction glEndList(). Le paramètre numList est
un numéro unique (index)qui est généré par glGenLists() et qui identifie la liste.
Les éléments stockés dans la liste d'affichage sont dessinés par l'instruction glCallList()
Une fois qu'une liste a été définie, il est impossible de la modifier à part en la détruisant et en la
redéfinissant.
Listes d'affichage hiérarchiques
Il est possible de créer une liste d'affichage qui exécute une autre liste d'affichage, en appelant
glCallList() à l'intérieur d'une paire glNewList() et glEndList().
Il y a un nombre maximal d'imbrications qui dépend des implémentations d'OpenGL.
Quadriques
La bibliothèque GLU permet de créer certains objets définis par une équation quadratique : des sphères,
des cylindres, des disques et des disques partiels. Pour celà il y a cinq étapes :
1. Utiliser gluNewQuadric() pour créer une quadrique.
2. Spécifier les attributs de rendu :
• gluQuadricOrientation() indique la direction des normales vers l'extérieur ou
l'intérieur.
• gluQuadricDrawStyle() indique le style de rendu : avec des points, des lignes ou des
polygones pleins.
• gluQuadricNormals() permet de générer des normales pour chaque face ou pour
chaque sommet.
• gluQuadricTexture() permet de générer les coordonnées de texture.
3. Indiquer la fonction qui traite les erreurs dans l'affichage de la quadrique par
gluQuadricCallback()
4. Afficher la quadrique désirée avec gluSphere(), gluCylinder(), gluDisk(), ou
gluPartialDisk(). Pour une meilleure efficacité, il est recommandé d'utiliser des listes
d'affichage.
5. Enfin, pour détruire l'objet, appeler gluDeleteQuadric().
IV. Textures
Introduction
Le placage de texture consiste à placer une image (la texture ) sur un objet. Cette opération se comprend
aisément lorsqu'il s'agit de plaquer une image rectangulaire sur une face rectangulaire, tout au plus
imagine-t-on au premier abord qu'il y a un changement d'échelle à effectuer sur chacune des dimensions.
Mais peut-être au contraire le choix est de répéter l'image un certain nombre de fois sur la face.
Se pose ensuite la question d'objets qui ne sont pas des faces rectangulaires : comment définir la portion
d'image et la manière de la plaquer ?
Comment procéder de manière générale
• Il s'agit d'abord de créer un Objet-Texture et de spécifier la texture que l'on va utiliser.
• Ensuite choisir le mode de placage de la texture avec glTexEnv[f,i,fv,iv]()
• Le mode decal décalque la texture sur l'objet : la couleur de l'objet est remplacée par
celle de la texture.
• Le mode modulate utilise la valeur de la texture en modulant la couleur précédente de
l'objet.
• Le mode blend mélange la couleur de la texture et la couleur précédente de l'objet.
• Puis autoriser le placage de textures avec glEnable(GL_TEXTURE_2D) si la texture a deux
dimensions. (ou GL_TEXTURE_1D si la texture est en 1D).
• Il est nécessaire de spécifier les Les coordonnées de texture en plus des coordonnées
géométriques pour les objets à texturer.
On assigne avec glTexCoord*() pour chaque sommet des objets à texturer un couple de valeurs qui
indique les coordonnées de texture de ce sommet.
Exercice
• Examinez le programme texture1.c (il utilise l'image [Link]) pour comprendre
l'utilisation des coordonnées de texture.
• Plaquez uniquement la tête de snoopy sur le quadrilatère grâce aux coordonnées de texture.
Répétition de la texture
Il faut indiquer comment doivent être traitées les coordonnées de texture en dehors de l'intervalle
[0.0, 1.0]. Est-ce que la texture est répétée pour recouvrir l'objet ou au contraire "clampée" ?
Pour ce faire, utilisez la commande glTexParameter() pour positionner les paramètres
GL_TEXTURE_WRAP_S pour la dimension horizontale de la texture ou GL_TEXTURE_WRAP_T pour la
dimension verticale à GL_CLAMP ou GL_REPEAT.
Exercice
• Dans la moitié inférieure du quadrilatère, plaquez trois fois l'image du snoopy.
Les Objets-Textures
Depuis la version 1.1 d'OpenGL, il est possible de déclarer, de nommer et de rappeler simplement des
Objets-Textures.
• glGenTextures(GLsizei n, GLuint *textureNames) renvoie n noms (des numéros, en fait) de textures
dans le tableau textureNames[]
• glbindTexture(GL_TEXTURE_2D, GLuint textureNames) a trois effets différents :
• la première fois qu'il est appelé avec une valeur textureNames non nulle, un nouvel Objet-
27/09/03 Page 17/19
Eric Bittard Cours OpenGL
Filtrage
Notez que les pixels de l'image de texture s'appellent des texels (au lieu de picture-elements, on a des
texture-elements).
Lorsque la partie de l'image de texture qui est mappée sur un pixel d'un objet est plus petite qu'un texel, il
doit y avoir agrandissement.
Lorsqu'au contraire la partie de l'image de texture qui est mappée sur un pixel d'un objet contient plus
d'un texel, il doit y avoir une réduction.
La commande glTexParameter() permet de spécifier les méthodes d'agrandissement (
GL_TEXTURE_MAG_FILTER ) et de réduction ( GL_TEXTURE_MIN_FILTER ) utilisées :
• GL_NEAREST choisit le texel le plus proche
• GL_LINEAR calcule une moyenne sur les 2x2 texels les plus proches.
L'interpolation produit des images plus lisses, mais prend plus de temps à calculer. Le compromis
valable pour chaque application doit être choisi.
Exercice
Récupérez deux images de textures (images qui peuvent se répéter) et plaquez l'une sur le bras de votre
robot, l'autre sur l'avant-bras et les doigts.
Enjoy !