Vous êtes sur la page 1sur 69

Synthse dimages 3D avec OpenGL

Rmy Malgouyres LAIC, IUT, dpartement info B.P. 86 63172 AUBIERE cedex http ://laic.u-clermont1.fr/ mr/

Table des matires


1 Interface GLUT 1.1 Compiler avec la glut . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Initialiser une fentre graphique . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 vennements de la glut . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Dessiner des formes de base 2.1 Les primitives gomtriques . . . . . . . . . 2.2 Variantes de glVertex*() et reprsentations 2.3 Modes dachage de polygones . . . . . . . 2.4 Reprsentation dun maillage . . . . . . . . . . des . . . . . . . . . . sommets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 3 3 4 10 10 13 14 14 17 17 17 18 19 22 23 29 32 33 35 35 36 40 41 41 46 46 52 54

3 Positioner camras et objets 3.1 Grer la camra et la perspective . . . . . . . . . 3.2 Coordonnes homognes . . . . . . . . . . . . . . 3.3 Changements de repre et coordonnes homognes 3.4 Camras et projections . . . . . . . . . . . . . . . 3.5 Positionnement quelconque dune camra . . . . . 3.6 Transformation de visualisation dans OpenGL . . 3.7 Positionner un objet dans une scne . . . . . . . . 3.8 Rotation, translation et changement dchelle . . 3.9 Pile de matrices . . . . . . . . . . . . . . . . . . .

4 clairage 4.1 limination des parties caches . . . . . . . . . . . 4.2 Sources de lumire et matriaux . . . . . . . . . . . 4.3 Vecteurs normaux . . . . . . . . . . . . . . . . . . . 4.4 clairement plat et lissage de Gouraud . . . . . . . 4.5 Grer la position et direction des sources lumineuses

5 Aspects avancs du rendu 5.1 Optimisation de lachage : Vertex Arrays . . . . . . . . . . . . . . . . . . . . . 5.2 Plaquage de textures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.3 Plaquage de textures avec OpenGL . . . . . . . . . . . . . . . . . . . . . . . . .

A Aide mmoire dopenGL 62 A.1 Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 A.2 vennements, GLUT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 A.3 Couleur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 1

TABLE DES MATIRES A.4 Paramtres de la camra . . . . . . A.5 Position, transformations, rotations A.6 Sommets . . . . . . . . . . . . . . . A.7 Points, segments, polygones . . . . A.8 Dessin, formes . . . . . . . . . . . . A.9 Achage 3D et clairage . . . . . . A.10 Vertex Arrays . . . . . . . . . . . . A.11 Temps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 65 65 65 66 67 67 68

Chapitre 1 Interface GLUT


OpenGL est une bibliothque graphique qui permet de faire de la visualisation 2D et 3D avec une acclration hardware (utilisation de la carte graphique). La librairie OpenGL peut tre utilise en combinaison avec la glut, qui permet de crer une fentre graphique et de grer les vennements tels que le click de souris ou le redimensionnement de la fentre par lutilisateur.

1.1

Compiler avec la glut

Pour pouvoir compiler un programme C ou C ++ avec la glut, il faut inclure la bibliothque glut.h : #include <GL/glut.h> Pour compiler, il faut utiliser la librairie lglut. Sous linux ou unix avec le compilateur gcc, la ligne de commande est : $ gcc programme.c -lglut -o programme.exe (on ferait de mme pour compiler un programme C + + avec le compilateur g + +).

1.2

Initialiser une fentre graphique

Voici un programme glut minimal qui cre une fentre graphique pour des animations 3D (et qui ne fait rien dautre). Le lecteur trouvera des commentaires sur les direntes fonctions dans lannexe A #include <GL/glut.h> /* variables globales : */ /* position de la fentre graphique dans lcran : */ GLushort pos_x_fenetre=100, pos_y_fenetre=100; /* dimensions de la fentre graphique : */ 3

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

GLushort largeur_fenetre==400, hauteur_fenetre=400; int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH); glutInitWindowPosition(pos_x_fenetre,pos_y_fenetre); glutInitWindowSize(largeur_fenetre,hauteur_fenetre); glutCreateWindow("OpenGL et glut : TP1"); glEnable(GL_DEPTH_TEST); glutMainLoop(); return 0; }

1.3

vennements de la glut

Les vnements dans un programme informatique sont les interventions de lutilsateur par le biais de la souris, du clavier, dun joystick, ect...

1.3.1

Lachage

Lvnement dachage a lieu chaque fois que la vue doit tre rafrachie. La fonction dachage (ou display function) doit alors redessiner les objets. Lachage a lieu notament dans les circonstances suivantes : Cration de la fentre graphique ; Passage de la fentre au premier plan ; Appel explicite du programmeur (voir la fonction glutPostRedisplay) lorsquil le juge ncessaire. Avec la glut, on doit dclarer la fonction dachage en utilisant la fonction glutDisplayFunc, qui prend en paramtre un pointeur de fonctions. La fonction glutDisplayFunc a pour prototype : void glutDisplayFunc(void (*func)(void)); cest dire quelle prend en paramtre une fonction dachage qui, elle, ne prend aucun paramtre. Exemple. Avec la fonction dachage suivant, le programme ne fait quacher une fentre qui est un rectangle rouge (couleur du fond). ... void Affichage(void ) { glClearColor(1,0,0,0); /* coefficients RGB + A de la couleur de fond */ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); /* effaage */ 4

Chapitre 1 : Interface GLUT glutSwapBuffers(); } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH); glutInitWindowPosition(pos_x_fenetre,pos_y_fenetre); glutInitWindowSize(largeur_fenetre,hauteur_fenetre); glutCreateWindow("OpenGL et glut, TP 1"); glEnable(GL_DEPTH_TEST); glutDisplayFunc(Affichage); glutMainLoop(); return 0; } /* appel de glutDisplayFunc */ /* Envoyer le buffer lcran */

1.3.2

Les frappes de touches clavier

Les vnements lis aux touches du clavier peuvent tre dclarer grace aux fonctions glutKeyboardFunc (pour les caractres usuelles) et glutSpecialFunc (pour les touches spciales telles que F 1, F 2, les ches, etc...). Exemple. Dans le programme suivant, la couleur du fond est grise de plus en plus claire lorsquon appuie sur la che droite au clavier, et de plus en plus fonce lorsquon appuie sur la che gauche. Le programme se termine lorsquon appuie sur la touche q. ... GLfloat niveau_de_gris=0.5; void Affichage(void ) { /* coefficients RGB + A de la couleur de fond : */ glClearColor(niveau_de_gris,niveau_de_gris,niveau_de_gris,0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); /* effaage */ glutSwapBuffers(); /* Envoyer le buffer lcran */ } void Special(int touche, int x, int y) { switch(touche) { case GLUT_KEY_LEFT: niveau_de_gris -= 0.05; if(niveau_de_gris < 0) niveau_de_gris = 0; 5

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

break; case GLUT_KEY_RIGHT: niveau_de_gris += 0.05; if(niveau_de_gris > 1) niveau_de_gris = 1; break; default: fprintf(stderr,"Touche non gre\n"); } glutPostRedisplay(); /* rafrachissement de laffichage */ } void Clavier(unsigned char key, int x, int y) { switch (key) { case q: exit(0); default: fprintf(stderr,"Touche non gre\n");break; } glutPostRedisplay(); /* rafrachissement de laffichage */ }

int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH); glutInitWindowPosition(pos_x_fenetre,pos_y_fenetre); glutInitWindowSize(largeur_fenetre,hauteur_fenetre); glutCreateWindow("OpenGL et glut, TP 1"); glEnable(GL_DEPTH_TEST); glutDisplayFunc(Affichage); glutKeyboardFunc(Clavier); /* appel de glutKeyboardFunc */ glutSpecialFunc(Special); /* appel de glutSpecialFunc */ glutMainLoop(); return 0; }

1.3.3

Gestion de la souris

La fonction grant lvnement de pression sur un bouton de la souris est dclare par la fonction glutMouseFunc. La fonction grant le mouvement de la souris avec un bouton press 6

Chapitre 1 : Interface GLUT est dclare par la fonction glutMotionFunc. Exemple. Dans le programme suivant, lorsquon dplace la souris vers la droite, la couleur du fond devient plus bleue. Lorsquon dplace la souris vers la gauche la couleur du fond devient moins bleue. Lorsquon dplace la souris vers le haut, la couleur du fond devient plus verte. Lorsquon dplace la souris vers le bas, la couleur du fond devient moins verte. ... GLint mousex, mousey; /* permet de mmoriser la dernire position */ /* de la souris */ GLfloat cof_g=0.5, coef_b=0.5; int leftButtonDown=0; void Affichage(void ) { /* coefficients RGB + A de la couleur de fond : */ glClearColor(0, coef_g, coef_b, 0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); /* effaage */ glutSwapBuffers(); /* Envoyer le buffer lcran */ } void PresseBouton(int button, int state, int x, int y) { if (button==GLUT_LEFT_BUTTON) { if (state==GLUT_DOWN) { leftButtonDown = 1; mousex = x; /* mmorisation des coordonnes de la souris */ mousey = y; /* lorsquon enfonce le bouton gauche */ } if (state==GLUT_UP) { leftButtonDown = 0; } } } void BougeSouris(int x, int y) { if (leftButtonDown==1) { coef_b += 0.01*(x-mousex); if(coef_b > 1) coef_b = 1; if(coef_b < 0) 7

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

coef_b = 0; coef_g += 0.01*(y-mousey); if(coef_g > 1) coef_g = 1; if(coef_g < 0) coef_g = 0; mousex = x; /* enregistrement des nouvelles */ mousey = y; /* coordonnes de la souris */ { glutPostRedisplay(); }

int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH); glutInitWindowPosition(pos_x_fenetre,pos_y_fenetre); glutInitWindowSize(largeur_fenetre,hauteur_fenetre); glutCreateWindow("OpenGL et glut, TP 1"); glEnable(GL_DEPTH_TEST); glutDisplayFunc(Affichage); glutKeyboardFunc(Clavier); glutSpecialFunc(Special); glutMouseFunc(PresseBouton); glutMotionFunc(BougeSouris); glutMainLoop(); return 0; }

/* appel de glutMouseFunc */ /* appel de glutMotionFunc */

1.3.4

vennement Idle : animation

Lvennement Idle est un vennement qui se produit rgulirement lorsquaucun autre vennement ne survient. Lvennement Idle permet de faire des animations en modiant ltat de la vue pour crer du mouvement. Dans le programme suivant, la couleur du fond de limage varie en fonction du temps. #include <math.h> ... GLfloat cof_g=0.5, coef_b=0.5; GLint parametre=0; GLfloat vitesse=0.1; 8

Chapitre 1 : Interface GLUT

void Affichage(void ) { /* coefficients RGB + A de la couleur de fond : */ glClearColor(0, coef_g, coef_b, 0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); /* effaage */ glutSwapBuffers(); /* Envoyer le buffer lcran */ } void IdleFunction(void ) { coef_b = sin(vitesse*parametre); parametre++; glutPostRedisplay(); }

int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH); glutInitWindowPosition(pos_x_fenetre,pos_y_fenetre); glutInitWindowSize(largeur_fenetre,hauteur_fenetre); glutCreateWindow("OpenGL et glut, TP 1"); glEnable(GL_DEPTH_TEST); glutDisplayFunc(Affichage); glutKeyboardFunc(Clavier); glutSpecialFunc(Special); glutIdleFunc(IdleFunction); glutMainLoop(); return 0; }

/* appel de glutIdleFunc */

Chapitre 2 Dessiner des formes de base


La principale opration dachage est le dessin dun polygone (triangle, quadrilatre,...) lcran. En eet, lorsquon souhaite reprsenter une surface autre quun polygone, on doit approcher cette surface par un maillage compos de polygones (voir la gure 2.1 et la gure 2.2).

(a) Exemple de surface

(b) Aproximation par un maillage

Fig. 2.1: Lapproximation dune surface par des polygones (maillage de surface).

2.1

Les primitives gomtriques

Lorsquon dcrit un polygone, on doit mettre les sommets du polygone entre un appel la fonction glBegin() et un appel glEnd(). Plusieurs primitives gomtriques peuvent tre dessines, suivant largument pass glBegin() (voir la gure 2.3). Exemple 1. Pour dessiner un triangle rempli, on peut faire : glBegin(GL_TRIANGLES); glVertex2f(0.0, 0.0); glVertex2f(1.0, 0.0); 10

Chapitre 2 : Dessiner des formes de base

Fig. 2.2: Exemple de maillage : reconstruction du Stanford Bunny. glVertex2f(0.0, 1.0); glEnd(); Exemple 2. Pour dessiner un hexagone rgulier rempli, on peut faire (en incluant la bibliothque math.h) : GLint i; glBegin(GL_POLYGON); for (i=0 ; i<6 ; i++) glVertex2f(cos(2*i*M_PI/6), sin(2*i*M_PI/6)); glEnd();

11

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

V1

V3

V5

V0

V2

V4

(a) GL_POINTS
V1
V1 V3 V5 V1 V3 V5

V2

V3 V0
V0 V2 V4 V0 V2 V4

V4 V5

(b) GL_LINES

(c) GL_LINE_STRIP

(d) GL_LINE_LOOP

V1

V2 V3

V1 V1 V3 V5

V3

V5

V0
V0 V0 V2 V4 V2 V4

V4 V5
(g) GL_TRIANGLE_FAN
V2

(e) GL_TRIANGLES

(f) GL_TRIANGLE_STRIP

V1

V3

V3

V2

V5

V6

V1

V3

V5

V7

V0 V4

V0

V1

V4

V7

V0

V2

V4

V6

V5

(h) GL_QUADS

(i) GL_QUAD_STRIP

(j) GL_POLYGON

Fig. 2.3: Types de primitives gomtrique. Le polygone doit tre convexe.

12

Chapitre 2 : Dessiner des formes de base Les arguments possibles pour la fonction glBegin(), qui correspondent direntes primitives gomtriques, sont : GL_POINTS : seuls des points sont dessins. (Lpaisseur des points peut tre rgle avec la fonction glPointSize()). GL_LINES : Des segments de droites sont dessines entre V0 et V1 , entre V2 et V3 , etc., les Vi tant les sommets successifs dnis par des appels glVertex*(). (Lpaisseur des droites peut tre rgle avec la fonction glLineWidth). GL_LINE_STRIP : Une ligne polygonale est trace. GL_LINE_LOOP : Une ligne polygonale ferme est trace. GL_TRIANGLES : des triangles sont dessins entre les trois premiers sommets, entre les trois suivants, etc... Si le nombre de sommets nest pas multiple de 3, les 1 ou 2 derniers sommets sont ignors. GL_TRIANGLE_STRIP : Des triangles sont dessins entre V0 , V1 , V2 , puis entre V1 , V2 , V3 , entre V2 , V3 , V4 , etc. GL_TRIANGLE_FAN : Un ventail est dessin form des triangles V0 , V1 , V2 , puis V0 , V2 , V3 , etc. GL_QUADS : Un quadrilatre est un polygone 4 sommets. Des quadrilatres sont dessins entre les quatre premiers sommets, puis entre les 4 suivants, etc. GL_QUAD_STRIP : Une srie de quadrilatres sont dessins entre V0 , V1 , V3 , V2 , puis, V2 , V3 , V5 , V4 , puis V4 , V5 , V7 , V6 , etc. GL_POLYGON : Un polygone ferm rempli est dssin. Le polygone doit tre convexe faute de quoi le comportement est indni (dpend de limplmentation).

2.2

Variantes de glVertex*() et reprsentations des sommets

Lorsquon spcie un sommet, celui-ci est toujours dans lespace trois dimensions R3 . On peut spcier, 2, 3, ou mme 4 coordonnes pour un point. Lorsquon ne spcie que 2 des coordonnes, la troisime coordonne est considre comme valant 0 (point situ dans le plan xOy). Lorsquon spcie 4 coordonnes, il sagit de la reprsentation du point en coordonnes homognes (voir la partie 3.2). De plus, on peut spcier les coordonnes soit par une liste de paramtres, soit par un tableau (vecteur) de coordonnes. Enn, les coordonnes peuvent tre de dirents types (GLint, GLfloat, GLdouble, etc.) chacune de ces options correspond une fonction glVertex*() : glVertex2f : deux paramtres ottants en simple prcision de type GLfloat (la troisime coordonne vaut 0) ; glVertex3f : trois paramtres ottants en simple prcision (la troisime coordonne vaut 0) glVertex2fv : un paramtre de type tableau de 2 GLfloats. glVertex3fv : un paramtre de type tableau de d GLfloats. glVertex2d, glVertex3d, glVertex2dv, glVertex3dv : similaires aux prcdents mais avec des oats en double prcision de type GLdouble. glVertex2i, glVertex3i, glVertex2di, glVertex3di : similaires aux prcdents mais avec des entiers 32 bits de type GLint. 13

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

V4 V0 V3 V1 V2

V1 V0 V2 V4 V3
(b) Sens GL_CW (clockwise)

(a) Sens GL_CCW (counterclockwise)

Fig. 2.4: Orientation dun polygone. Par dfaut, la vue de face correspond au cas GL_CCW

2.3

Modes dachage de polygones

Les polygones en 3D ont deux cots : le devant et le derire. Par dfaut, un polygone est vu de face (voir la gure 2.4) si sa projection dans la fentre graphique voit la liste de se sommets dans lodre poisitif trigonomtrique (on peut changer ce comportement avec la fonction glFrontFace). On peut spcier un mode dachage dirents pour les polygones vus de face et pour les polygones vus de dos par la fonction glPolygonMode. void glPolygonMode(GLenum face, GLenum mode); face peut tre GL_FRONT, GL_BACK ou GL_FRONT_AND_BACK ; mode peut tre GL_POINT (dessin uniquement des sommets du polygone), GL_LINE (dessin des contours du polygone) ou GL_FILL (dessin du polygone avec remplissage). Enn, on peut liminer les faces (par exemple) qui sont vues de dos pour acclrer lachage, (si lobjet est ferm et vu de lextrieur, on sait quaucune face vue de dos ne sera visible car elles seront caches par dautres faces. Pour cela, il faut activer le culling par glEnable(GL_CULL_FACE); et indiquer le type de polygones liminer par lusage de la fonction void glCullFace(GLenum mode). face peut tre GL_FRONT, GL_BACK ou GL_FRONT_AND_BACK.

2.4
2.4.1

Reprsentation dun maillage


Dnition dun maillage

Un maillage P dans lespace tridimensionnel R3 est la donne de : 1. Une suite de points P0 , P1 , . . . , Pn1 de R3 appels sommets du maillage ; 2. Un ensemble de faces, chaque face tant une suite de numros de sommets dans {0, . . . , n 1}. 14

Chapitre 2 : Dessiner des formes de base

2.4.2

Exemple

Fig. 2.5: Exemple de maillage : un ttradre. Par exemple, considrons le ttradre construit sur les quatre points A = (400, 400, 10), B = (700, 700, 10), C = (0, 500, 10) et D = (500, 0, 500) (voir gure 2.5). Le maillage correspondant est la donne de : 1. Les sommets P0 = A, P1 = B, P2 = C, et P3 = D ; 2. Les quatre faces qui sont : La face numro 0 reprsentant le triangle OAB : (0, 1, 2) ; La face numro 1 reprsentant le triangle OAC : (0, 1, 3) ; La face numro 2 reprsentant le triangle OBC : (0, 2, 3) ; La face numro 3 reprsentant le triangle ABC : (1, 2, 3). Voici un programme achant le ttradre comme reprsent sur la gure 2.5 : #include <GL/glut.h> #include <stdio.h> #include <stdlib.h> GLushort largeur_fenetre=700; GLushort hauteur_fenetre=700; GLint nvertices=4, nfaces=4; GLfloat vertices[][3] = { {400.0, 400.0, -10.0}, {700.0, 700.0, -10.0}, {0.0, 500.0, -10.0}, {500.0, 0.0, -500.0} }; GLuint faces[][3] = { 15

Rmy Malgouyres, Universit Clermont 1 {0, {0, {0, {1, }; 1, 1, 2, 2, 2}, 3}, 3}, 3}

http ://laic.u-clermont1.fr/ mr/

OpenGL

void Affichage(void ) { int i, j; glClearColor(1.0,1.0,1.0,1.0); glClear(GL_COLOR_BUFFER_BIT); glColor3f(0.0, 0.0, 0.0); glLineWidth(2); glBegin(GL_TRIANGLES); for (i=0 ; i<nfaces ; i++) for (j=0 ; j<3 ; j++) glVertex3fv(vertices[faces[i][j]]); glEnd(); glutSwapBuffers(); } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE); glutInitWindowPosition(100,100); glutInitWindowSize(largeur_fenetre,hauteur_fenetre); glutCreateWindow("Dessin dun ttradre"); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glutDisplayFunc(Affichage); /* Dfinition du volume visible */ /* Ncessaire pour afficher des objets gomtriques */ /* voir Chapitre suivant pour personaliser */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0,largeur_fenetre , 0, hauteur_fenetre, 1, 600); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glutMainLoop(); return 0; } /* Envoyer le buffer lcran */

16

Chapitre 3 Positioner camras et objets


3.1 3.2
3.2.1

Grer la camra et la perspective Coordonnes homognes


Dnition des coordonnes homognes

On introduit un systme de coordonnes dirent des coordonnes cartsiennes pour reprer les points dans lespace 3D. Pour cel, on ajoute une composante W non nulle aux trois composantes (x, y, z). Ainsi, un point M de lespace 3D sera repr en coordonnes homognes par un quadruplet : M(x, y, z, W ) Les coordonnes de M ne sont pas uniques, mais deux quadruplets (x, y, z, W ) et (x , y , z , W ) reprsentent le mme point si ces quadruplets sont multiples lun de lautre (lis dans R3 ). Connaissant les coordonnes cartsiennes (x, y, z) dun point M, on peut obtenir un reprsentant de M en coordonnes homognes par (x, y, z, 1) (cest dire que W = 1). Connaissant un reprsentant (x, y, z, W ) de M en coordonnes homognes, on peut obtenir y x z les coordonnes cartsiennes de M par M = ( W , W , W ). Lintrt de reprsenter les points par des coordonnes homognes est de pouvoir reprsenter toute application ane par une seule matrice, comprenant la partie linaire et la translation.

3.2.2

Coordonnes homognes et applications anes

Pour eectuer une translation T de vecteur = (xv , yv , zv ) en coordonnes homognes, il v sut de faire une multiplication matricielle : x + xv x 1 0 0 xv x y 0 1 0 yv y y + yv T = z 0 0 1 zv . z = z + zv 1 1 0 0 0 1 1 Pour appliquer une application linaire f dont la a1,1 a1,2 a2,1 a2,2 Mf = a3,1 a3,2 17 matrice en coordonnes cartsienne est : a1,3 a2,3 a3,3

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

il sut de faire en coordonnes homognes la a1,1 a2,1 Mf = a3,1 0

multiplication matricielle par la matrice a1,2 a1,3 0 a2,2 a2,3 0 a3,2 a3,3 0 0 0 1

Nimporte quelle application ane, compose dune application linaire et dune translation, peut tre obtenue en coordonnes homognes par la multiplication par une matrice : a1,1 a1,2 a1,3 xv a a a y M = 2,1 2,2 2,3 v a3,1 a3,2 a3,3 zv 0 0 0 1 La matrice en coordonnes homognes Mf g de la compose de deux application anes f et g est le produit Mf .Mg des matrices associes aux applications anes en coordonnes homognes. De mme, la matrice Mf 1 en coordonnes homognes de linverse dune application ane bijective est linverse M1 de la matrice de cette application ane. f

3.3

Changements de repre et coordonnes homognes


anes (O, , , k ) et (O , , , k1 ) tels que 1 1 = a1,1 + a2,1 + a3,1 k = a1,2 + a2,2 + a3,2 k , = a1,3 + a2,3 + a3,3 k point P dans le deuxime repre partir a1,3 a2,3 . a3,3

Si lon se donne deux repres 1 1 k1

On peut calculer les coordonnes X, Y et Z du des coordonnes x, y et z dans le premier repre. En notant a1,1 a1,2 M = a2,1 a2,2 a3,1 a3,2

la matrice de passage du changement de base, la matrice de passage M est automatiquement inversible. En notant (Ox , Oy , Oz ) les coordonnes du point O dans le repre (O, , , k ), on a : Ox X x Y = M 1 . y Oy Z z Oz En inversant les formules, on peut aussi calculer les coordonnes x, y et z dans le premier repre en fonction des coordonnes X, Y et Z dans le second repre : Ox x X y = M. Y + Oy . z Z Oz 18

Chapitre 3 : Positioner camras et objets

A C B

A C B

A
A C B Plan de projection

C B

Plan de projection

Centre de projection

(a) La projection parallle

(b) La projection en perspective

Fig. 3.1: Les deux principaux types de projection. Ces formules sont des formules de transformations anes homognes a1,1 a1,2 a1,3 Ox x y a2,1 a2,2 a2,3 Oy = z a3,1 a3,2 a3,3 Oz . 0 0 0 1 1 qui scrivent en coordonnes X Y Z 1

Un changement de repre ane consiste donc en une multiplication matricielle en coordonnes homognes.

3.4

Camras et projections

Nous voyons ici comment projeter des donnes 3D sur un plan dans le but de visualiser ces donnes. Nous considrons ici des projections trs particulires, le plan sur lequel on projette tant perpendiculaire au troisime axe de coordonnes Oz. Ceci correspondra au point de vue trs particulier dun observateur plac sur lorigine O et regardant dans la direction de laxe des z. Par des changements de repres appropris, on remne le cas dun point de vue quelconque de lobservateur au cas particulier trait ici.

3.4.1

Projection parallle

La projection parallle est la projection sur un plan paralllement une direction (voir gure 3.1a). Cette projection correspond un observateur plac linni. Elle est simple, mais nest pas trs raliste. Plaons nous dans un repre (O, , , k ) tel que le plan de projection soit le plan z = 0 et la direction de projection soit parallle au vecteur k . Pour obtenir le projet dun point (x, y, z), il sut doublier la coordonne z : Le projet a pour coordonnes : xp = x, yp = y, zp = 0. Les formules de cette projection sont donc particulirement simples.

3.4.2

Projection en perspective

Dans le modle de camra Pinhole, il y a un centre de projection (voir gure 3.1b), qui correspond la position de lobservateur. Ce modle de camra est plus raliste que le modle 19

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

Fig. 3.2: Le modle de camra pinhole


(x, y, z)

(xp, yp, d) C = (0, 0, 0) Plan de lcran d z

Fig. 3.3: Calcul des coordonnes du projet. avec projection parallle. Par contre, les formules donnant les coordonnes du projet (xp , yp , zp ) dun point en fonction des coordonnes (x, y, z) du point sont un peu plus compliques.

3.4.3

Calcul des coordonnes du projet dun point

Plaons nous dans un repre (O, , , k ) li la camra, tel que le plan de projection soit le plan dquation z = d et tel que le centre de projection ait pour coordonnes (0, 0, 0) (voir gure 3.2). La troisime coordonne zp du projet sera videmment gale d de part la dnition du plan de projection. Daprs le thorme de Thals (voir gure 3.3), on a : x yp y xp = et = d z d z En multipliant ces galits par d, on obtient : 20

Chapitre 3 : Positioner camras et objets d d et yp = y z z En coordonnes homognes, ces formules scrivent : xp = x d xz xp yp y d z zp = d 1 1 Do, xp yp = M. zp 1 avec 1 0 M= 0 0 0 0 0 1 0 0 0 1 0 1 0 d 0 x y z 1 x y z
z d

La projection en perspective sexprime donc par la multiplication par une matrice en coordonnes homognes.

3.4.4

Camra Pinhole

Une camra Pinhole est une spcication dun point de vue de lobservateur avec projection en perspective. Lide est celle dun observateur regardant une scne travers un trou dpingle (pin hole en anglais), qui est le centre de projection. Cela correspond lun des tout premiers modles historiques dappareil photo. On se place ici dans le cas o la camra est plac sur le point O = (0, 0, 0), la direction de vise tant laxe des z. Nous avons vu dans la partie 3.4.3 comment calculer les coordonnes du projet dun point en fonction du paramtre d donnant lquation z = d du plan de projection. Cependant, dans une application graphique 3D, le paramtre d nest pas donn directement, mais doit tre dtermin partir de langle douverture c de la camra et la largeur dimx de limage calculer. Langle douverture c est langle sous lequel lobservateur plac en O = (0, 0, 0) doit voir le rectangle de largeur dimx constitu par limage calculer, ce rectangle tant plac dans le plan z = d centr au point A = (0, 0, d) (voir la gure 3.4). On peut calculer comme suit la valeur de d partir de c et dimx . Soit B = ( dimx , 0, d) le point de limage calculer situ le plus droite par rapport 2 lobservateur. Le triangle OAB est rectangle en A, et langle en O de ce triangle est gal 2c . On a donc dimx AB = d = OA = c tan( 2 ) 2 tan( 2c ) 21

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/


dimx A d c O B

OpenGL

Fig. 3.4: Calcul de la profondeur d du plan de lcran


1 k O k C O k1 1

Fig. 3.5: Le repre li la camra

3.5
3.5.1

Positionnement quelconque dune camra


Repre li une camra

En synthse dimages, on considre des camras, qui dnissent le point de vue partir duquel lobservateur voit la scne. Chaque modle de camra correspond un type de projection dans lespace. Nous avons vu dans la partie 3.4 quil existe principalement deux types de projection, la projection parallle et la projection en perspective. Les algorithmes dachage 3D supposent que la camra (ou lobservateur) est plac au point O = (0, 0, 0), et regarde dans la direction de laxe Oz. Cette hypothse peut tre reformule comme suit : les coordonnes qui dnissent les objets (coordonnes des sommets de polydres), et les coordonnes des vecteurs normaux aux sommets de polydres, sont calcules dans un repre li la camra (voir les gures 3.5 et 3.10 ). Une scne 3D possde un repre xe (O, , , k ) dans lequel lutilisateur dnit les objets, les sources lumineuses, et la position de la camra. Ce repre sappelle le repre de la scne, ou le repre du monde. La camra possde un repre (O , , , k1 ) qui lui est propre, appel repre de la camra, 1 1 dont lorigine O concide avec la position de la camra, et tel que la direction k1 du troisime axe de coordonne concide avec la direction de vise de la camra. On associe donc la camra une matrice M = (ai,j )i,j=1,2,3 telle que : = a1,1 + a2,1 + a3,1 1 k = a + a + a 1 1,2 2,2 3,2 k = a + a + a k1 1,3 2,3 3,3 k Rappelons que M est la matrice de passage du repre de la scne au repre de la camra. 22

Chapitre 3 : Positioner camras et objets

3.5.2

Initialisation dune camra

Le but de cette partie est dexpliquer comment on peut calculer la matrice M = (ai,j )i,j=1,2,3 dune camra partir de la position et du point de focalisation (le centre) de cette camra. Soit O la position dune camra et C un point, appel le centre de la camra, vers lequel est dirig la camra. Calculer les coecients (ai,j ) de la matrice M associe la camra revient calculer les coordonnes des vecteurs , et k1 dans le repre (O, , , k ) de la scne. 1 1 Le vecteur k1 du repre de la camra, qui est le vecteur unitaire dans la direction de vise, est gal OC k1 = ||O C|| Nous avons un choix pour dnir les deuxime et troisime vecteur du repre de la camra. En eet, pour le moment, nous navons pas x exactement la position de la camra, qui peut tourner autour de laxe O C. Nous allons xer le vecteur de sorte que laxe des X du repre 1 de la camra soit perpendiculaire laxe des z du repre de la scne. De cette manire, laxe des z de la scne apparatra vertical lors de lachage, ce qui est assez naturel. Le vecteur doit donc tre orthogonal au troisime vecteur k du repre de la scne. De 1 plus, le vecteur doit tre orthogonal au vecteur k1 de la direction de vise, puisque nous 1 souhaitons obtenir un repre (O , , , k1 ) orthonorm. Nous navons pas beaucoup de choix, 1 1 et nous dnirons donc = k1 k 1 || k1 k || Enn, le vecteur doit tre la fois orthogonal et k1 , de manire ce que le repre 1 1 (O , , , k1 ) soit orthonorm direct. On a donc : 1 1 = k1 1 1 || k1 || 1

3.5.3

Transformation des objets dans le repre de la camra

Une fois la matrice M associe la camra initialise, dans le but dutiliser les algorithmes dachage, nous devons exprimer les coordonnes des sommets, ainsi que les vecteurs normaux aux sommets dans le cas dune utilisation du modle de Phong, dans le repre de la camra. Pour cela, on utilise simplement les formules de changement de base pour calculer les coordonnes (X, Y, Z) des sommets dans le repre de la camra partir de ses coordonnes (x, y, z) dans le repre de la scne. Les coordonnes de la position des sources lumineuses doivent subir la mme transformation.

3.6
3.6.1

Transformation de visualisation dans OpenGL


Principe des transformations gomtriques dans OpenGL

Avant dtre ach lcran, un objet subit plusieurs transformations (voir la gure 3.6). Dans lordre chronologique, OpenGL eectue les transformations suivantes : 23

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

1. La transformation du modle : les objets graphiques sont dnis dans un repre ou ils sont simples concevoir, puis on transforme ces objets par des rotations, translations et changements dchelle (anits) pour les mettre dans le repre du monde. On fait subir ces transformations aux objets au moyen des fonctions glRotatef, glTranslatef et glScalef dans le mode GL_MODELVIEW. 2. La transformation de la camra : une fois dans le repre du monde, tous les objets subissent un changement de repre vers le repre de la camra. On fait subir cette transformation aux objets au moyen des fonctions gluLookAt, glRotatef, glTranslatef et glScalef dans le mode GL_MODELVIEW. 3. Projection : une fois dans le repre de la camra, les objets subissent une projection vers une image 2D (dans un buer OpenGL). Pour rgler les paramtres de cette projection, on utilise la fonction gluPerspective dans le mode GL_PROJECTION. 4. Transformation 2D : une fois gnre limage 2D dans un buer, elle subit des changement dchelle sur les axes (anits orthogonales) pour tre ajuste aux dimensions de la fentre graphique lcran. Cette dernire transformation est paramtre par la fonction glViewport. Le principe de ces transformations est trs gnral, nous donons dans la suite une utilisation de base des fonctionalits dOpenGL en la matire.

3.6.2

Paramtres de la camra

Dans la fonction de redimensionnement (dclare dans glut par un appel de glutReshapeFunc, On peut rglr les paramtres de la projection et de la transformation 2D. 3.6.2.a La fonction glviewport

En gnral il nest pas commode de crer toutes les scnes de faon ce quelles se projettent directement sur la fentre graphique. On prfre utiliser des coordonnes normalises dans le plan (par exemple avec des coordonnes allant de 1 +1). La fonction glViewport spcie une transformation ane pour passer des coordonnes 2D de limage calcule aux coordonnes (en nombre de pixels) de la fentre (voir la gure 3.7). Ceci permet de choisir la portion du plan 2D qui sera visible. La fonction glViewport a pour prototype : void glViewport(GLint x0, GLint y0, GLsizei dimx, GLsizei dimy); o (x0 , y0) sont les coordonnes du milieu de la portion de plan visible souhaite ; L et H sont respectivement la largeur et la hauteur de la portion de plan visible souhaite. La transformation est dimx Xf enetre = (xnormalise + 1) + x0 2 dimy Yf enetre = (ynormalise + 1) + y0 2 Pour que laspect des objets soit prserv par la transformation cest dire pour que le changement dchelle soit le mme en x et en y, il faut que les rapports suivants soient gaux : largeur_fenetre dimx = dimy hauteur_fenetre 24

Chapitre 3 : Positioner camras et objets On note aspect = 3.6.2.b La fonction gluPerspective

dimx . dimy

La fonction gluPerspective permet de rgler les caractristiques de la cmra (voir la gure 3.8) telles que langle douverture y (en y). Lorsquon ache une scne avec OpenGL, seule une partie de la scne est visible. La partie qui 1. Se projette dans la portion de plan visible (de taille dimx dimy ) ; 2. Est comprise entre deux plans z = zproche et z = zeloigne . Le prototype de la fonction gluPerspective est le suivant : void gluPerspective(GLdouble GLdouble GLdouble GLdouble theta_y, aspect, z_proche, z_eloigne)

Avant dutiliser gluPerspective, il faut passer en mode GL_PROJECTION, et il faut rinitialiser la transformation de projection lidentit. En gnral, on appelle les fonctions glViewport et gluPerspective dans la fonction de redimentionnement de la fentre (avec la glut, cette fonction est dclare par un appel glutReshapeFunc dans le main. La fonction de redimensionnement est alors automatiquement appele lorsque lutilisateur redimentionne la fentre graphique. ... GLdouble theta_y=45; ... void Redimensionnement(int l, int h) { /* l et h sont les nouvelles dimensions de la fentre */ largeur_fenetre = l; /* mise jour des variables */ hauteur fenetre = h; glViewport(0,0,(GLsizei)largeur_fenetre,(GLsizei)hauteur_fenetre); glMatrixMode(GL_PROJECTION); /* passage en mode GL_PROJECTION */ glLoadIdentity(); /* rinitialisation de la matrice de transformation */ gluPerspective(theta_y,l/(GLdouble)h, 0.01, 10000); glMatrixMode(GL_MODELVIEW); /* repassage en mode GL_MODELVIEW */ } int main(void ) { glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH); glutInitWindowPosition(pos_x_fenetre,pos_y_fenetre); glutInitWindowSize(largeur_fenetre,hauteur_fenetre); 25

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

objets graphiques

transformation du modle

transformation de la camra

projection

transformation 2D

image lcran

glRotatef glTranslatef glScalef

gluLookAt glRotatef glTranslatef glScalef

gluPerspective

glViewport

Fig. 3.6: Les transformations gomtriques subies par les objets avant achage

Fig. 3.7: Les paramtres de glViewport

11111111111111111 00000000000000000 11111111111111111 00000000000000000 11111111111111111 00000000000000000 11111111111111111 00000000000000000 11111111111111111 00000000000000000 11111111111111111 00000000000000000 11111111111111111 00000000000000000 11111111111111111 00000000000000000 11111111111111111 00000000000000000 11111111111111111 00000000000000000 11111111111111111 00000000000000000 11111111111 11111111111111111 00000000000 00000000000000000 11111111111 11111111111111111 00000000000 00000000000000000 11111111111 11111111111111111 00000000000 00000000000000000 11111111111 11111111111111111 00000000000 00000000000000000 11111111111 11111111111111111 00000000000 00000000000000000 11111111111 11111111111111111 00000000000 00000000000000000 11111111111 11111111111111111 00000000000 00000000000000000 11111111111 00000000000 11111111111 00000000000 11111111111 00000000000 11111111111 00000000000 11111111111 00000000000

Fig. 3.8: Les paramtres de gluPerspective 26

Chapitre 3 : Positioner camras et objets glutCreateWindow("OpenGL et glut, TP 1"); glEnable(GL_DEPTH_TEST); glutDisplayFunc(Affichage); glutKeyboardFunc(Clavier); glutSpecialFunc(Special); glutMotionFunc(BougeSouris); glutMouseFunc(PresseBouton); glutReshapeFunc(Redimensionnement); glutMainLoop(); return 0; }

3.6.3

Positionnement de la camra

La fonction gluLookAt permet de modier du GL_MODELVIEW pour rgler la transformation de la camra (voir la gure 3.9).

Fig. 3.9: Les paramtres de gluLookAt Les paramtres de gluLookAt sont : 1. les coordonnes de la position (posx , posy , posz ) de la camra ; 2. Les coordonnes (Cx , Cy , Cz ) dun point dans la direction de vise (ce point est aussi appel le centre) ; 3. Les coordonnes dun vecteur V qui doit apparatre vertical dans limage obtenue par projection. 27

Rmy Malgouyres, Universit Clermont 1 Le prototype de gluLookAt est :

http ://laic.u-clermont1.fr/ mr/

OpenGL

void gluLookAt(GLdouble posx, GLdouble posy, GLdouble posz, GLdouble Cx, GLdouble Cy, GLdouble Cy, GLdouble Vx, GLdouble Vy, GLdouble Vz); La fonction gluLookAt doit tre utilise dans le mode GL_MODELVIEW. void Affichage(void ) { glClearColor(1.0,1.0,1.0,1.0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /* rinitialiation de la matrice de GL_MODELVIEW */ gluLookAt(10, 10, 10, /* rglage de la camra */ 0,0,0, 0,1,0); glColor3f(0.0,0.0,0.0); /* couleur des traits dessin en noir */ glutWireTeapot(5); /* dessin dune thire */ glutSwapBuffers(); /* Envoyer le buffer lcran */ }

28

Chapitre 3 : Positioner camras et objets

3.7
3.7.1

Positionner un objet dans une scne


Positioner un objet

Chaque objet 3D est construit et modlis dans un repre qui lui est propre, appel repre de lobjet. Pour positioner lobjet dans le repre du monde, nous eectuons un changement de repre (voir la gure 3.10). Dans ce cas, il importe de respecter un ordre pour les changements de repres successifs. Nous utiliserons dans ce chapitre lexpression matricielle en coodonnes homognes des changements de repre (voir la partie 3.2).

k0

k1

0
1
(a) repre li une chaise (b) repre li la camra

1 1

k1

k0

(c) repres du monde, de la chaise, et de la camra

Fig. 3.10: Les changements de repre dans la construction et le rendu dune scne 3D Pour tranformer lobjet de son repre vers le repre du monde, nous multiplierons les coordonnes des sommets ou des points de contrle par une matrice T . Cette matrice T transfor mera les vecteurs (1, 0, 0), (0, 1, 0) et (0, 0, 1) dans le repre de lobjet en des vecteurs 0 , 0 29

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

et k 0 (voir la gure 3.10). La matrice T nest autre que la matrice de passage du repre du monde au repre de lobjet. Pour passer du repre du monde au repre de la camra, nous multiplierons par la matrice M1 , o M est la matrice en coordonnes homognes associe la camra. La transformation totale appliquer un sommet ou un point de contrle P de lobjet sera (en coordonnes homognes) : P = M1 .T .P

3.7.2

Transformer un objet

Pour appliquer une transformation dun objet sur lui-mme, cest dire dans son propre repre (voir la gure 3.11b pour le cas dune rotation de 30 degrs), il faut multiplier la matrice de passage du repre du monde au repre de lobjet, droite, par la matrice R de la transformation. En coordonnes homognes, on obtient : P = M1 .T .R.P Considrons lexemple dune paralllpipde translat le long de laxe des z. Le repre de lobjet est translat par rapport au repre du monde. Pour faire une rotation dans le repre de lobjet, le paralllpipde doit subir dabord la rotation, puis la translation (voir la gure 3.11).

30

Chapitre 3 : Positioner camras et objets


jet x
x rep`re de lobjet e

l de

ob

y Translation z

(a) La position initiale


x rep`re du monde e

(b) Rotation dans le repre de la camra


b je e lo ere d rep`
x rep`re du monde e

ere d rep`

e lo

b jet

e `re rep

2. rotati

2. translation z
z

(c) Rotation dans le repre de lobjet

Fig. 3.11: Rotations dun objet initial autour de laxe Oz dans dirents repres. Pour eectuer une transformation de lobjet dans le repre du monde (voir la gure 3.11d), il faut muliplier gauche la matrice de passage du repre du monde au repre de lobjet par la matrice da la transformation : P = M1 .R.T .P Si lon reprend lexemple du paralllpipde de la gure 3.11 qui est translat le long de laxe des y, pour lui faire subir une rotation dans le repre du monde, lobjet doit au total subir dabord la translation, puis la rotation. Pour eectuer une transformation R du point de vue dans le repre de la camra (voir la gure 3.11c), il faut multiplier gauche linverse M1 de la matrice de passage du repre du monde au repre de la camra par la matrice R. (cel revient multiplier la matrice M droite par R1 ). En coordonnes homognes, on obtient : P = R.M1 .T .P Pour reprendre lexemple de la gure 3.11, la rotation a lieu aprs la projection sur le plan 2D. 31

1 ro t a t io n

y
1. translation

(d) Rotation dans le repre du monde

on

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

3.8
3.8.1

Rotation, translation et changement dchelle


Matrices GL_MODELVIEW et GL_PROJECTION

La succession de transformations que subit un objet avant dtre ach correspond une succession de produits de matrices. Les transformations 3D sont la composition de deux matrice 4 4 (voir la gure 3.12). 1. La matrice GL_MODELVIEW correspond la transformation du modle suivie de la transformation de la camra ; 2. La matrice GL_PROJECTION correspond la projection (transformation des coordonnes 3D en coordones 2D.
rep`re e de lobjet rep`re e du monde rep`re e de la camra e rep`re 2D e du plan rep`re 2D e de limage

objets graphiques

transformation du modle

transformation de la camra

projection

transformation 2D

image lcran

matrice GL MODELVIEW

matrice GL PROJECTION

viewPort

Fig. 3.12: Les matrices GL_MODELVIEW et GL_PROJECTION Toutes les transfomations 3D eectues par OpenGL (rotations, translations, changements dchelle, modication de la camra, de langle douverture, etc...) correspondent la multiplication droite de lune des deux matrices GL_MODELVIEW et GL_PROJECTION par une matrice. Pour modier lune des matrices GL_MODELVIEW ou GL_PROJECTION, il faut slectioner le mode correspondant par un appel glMatrixMode.

3.8.2
3.8.2.a

Les fonctions glRotatef, glTranslatef et glScalef


La fonction glRotatef

La fonction glRotatef permet de faire des rotations, cest dire de multiplier lune des matrices GL_MODELVIEW ou GL_PROJECTION par une matrice de rotation. Lorsquon veut faire tourner un objet dans le monde, on fait appel glRotatef dans le mode GL_MODELVIEW. On conoit que faire tourner le monde sur lui-mme ou faire tourner la camra autour du monde revient au mme du point de vue de limage obtenue. Ces deux choses se ralisent aussi dans le mode GL_MODELVIEW. Lappel de glRotatef provoque une multiplication droite par une matrice de rotation. En dautres termes, la rotation en question sera eectue avant toutes les autres transformations dj accumules dans le mode (GL_MODELVIEW ou GL_PROJECTION selon le cas). Le prototype de la fonction glRotatef est le suivant : void glRotatef(GLfloat angle, GLfloat vx, GLfloat vy, 32 GLfloat vz);

Chapitre 3 : Positioner camras et objets Les coordonnes vx, vy et vz sont celles dun vecteur directeur de laxe de rotation. Laxe de rotation passe toujour par lorigine (rotation vectorielle). Pour faire une rotation dautour dun axe ne passant pas par lorigine, il faut composer la rotation avec une translation. 3.8.2.b La fonction glTranslatef

La fonction glTranslatef permet de faire des translation, cest dire de multiplier lune des matrices GL_MODELVIEW ou GL_PROJECTION par une matrice de translation en coordonnes homognes. Lorsquon veut translater un objet dans le monde, ou encore le monde par rapport la camra, on fait appel glTranslatef dans le mode GL_MODELVIEW. Comme pour les rotations, lappel de glTranslatef provoque une multiplication droite par une matrice de translation. En dautres termes, la translation en question sera eectue avant toutes les autres transformations dj accumules dans le mode (GL_MODELVIEW ou GL_PROJECTION selon le cas). Le prototype de la fonction glTranslatef est le suivant : void glTranslatef(GLfloat vx, GLfloat vy, GLfloat vz);

Les coordonnes vx, vy et vz sont celles du vecteur de translation. 3.8.2.c La fonction glScalef

La fonction glScalef permet de faire des changlements dchelle sur les axes (anits orthogonales). Le prototype de la fonction glScalef est le suivant : void glScalef(GLfloat facteurx, GLfloat facteury, GLfloat facteurz);

Les coordonnes x des objets dessins aprs lappel glScalef sont multiplies par facteurx, les coordonnes y par facteury, et les coordonnes z par facteurz. la matrice de changement dchelle est donc ma suivantes : facteurx 0 0 0 0 facteury 0 0 0 0 facteurz 0 0 0 0 1 Comme pour les rotations et translations, lappel de glScalef provoque une multiplication droite par une matrice de changement dchelle. En dautres termes, le changement dchelle en question sera eectue avant toutes les autres transformations dj accumules dans le mode (GL_MODELVIEW ou GL_PROJECTION selon le cas).

3.9

Pile de matrices

Avec ce que nous avons vu jusqu prsent chaque appel glRotatef aectera tous les objets dessins par la suite. Les fonction glPushMatrix et glPopMatrix permettent dappliquer une transformation une partie des objets. Les matrices GL_MODELVIEW et GL_PROJECTION sont en fait des piles de matrices. La matrice courante est la matrice qui se trouve au sommet de la pile. 33

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

Lors de lappel glPushMatrix, la matrice de transformation courante (GL_MODELVIEW ou GL_PROJECTION selon le mode slectionn) est duplique, la copie est ajoute au sommet de la pile de matrices, et devient la matrice courante. Lors de lappel glPopMatrix, elle est dpile, et la matrice courante est restaure ltat davant lappel glPopMatrix. Toutes les transformations eectues entre les appels de glPushMatrix et glPopMatrix nauront aucun eet sur les objets dessins aprs le glPopMatrix. La structure de pile est particulirement adapte pour structurer les achage en dcomposant les objets en direntes parties. Par exemple, si lon souhaite dessiner une voiture (voir la gure 3.13). avec deux essieux et deux roues par essieu, on va dessiner le corps de la voiture,

Fig. 3.13: Dessin dune voiture on va translater pour dessiner lessieu et les roues avant, puis on va revenir la posistion de dpart, puis translater pour dessiner lessieu et les roues arrire, puis revenir la position de dpart. De mme , pour dessiner lessieu (par exemple avant), on va dessiner lessieu, translater pour dessiner la roue de gauche, revenir la position antrieure, translater pour dessiner la roue de droite, et revenir la position antrieure. Avec la structure de pile, on dessine le cors de la voiture, on duplique et on empile la matrice GL_MODELVIEW, on dessine lessieu et les roues, puis on dpile la matrice GL_MODELVIEW, ce qui restore la matrice ltat o elle tait lors du dessin du corps de la voiture.

34

Chapitre 4 clairage
4.1 limination des parties caches

Lorsquon ache des objets en 3D, certaines parties de la scne sont caches par dautres qui se trouvent plus proches de lobservateur. Ainsi, tel un peintre, lalgorithme dachage doit dessiner les objets plus proches en dernier pour que seuls ceux-ci soient visibles. On appelle ce procd llimination des parties caches. Lalgorithme du zbuer utilis par OpenGL permet dacher des scnes dont les objets sont des maillages. Si une scne comprend dautres types dobjets (sphres, quadriques, splines...), il faut facettiser ces surfaces (cest dire les approximer par des maillages pour pouvoir les acher. Dans lalgorithme du zbuer, on calcule une image discrte mmorise dans un framebuer . Lide de lalgorithme est de calculer, pour chaque pixel, le point de profondeur minimale pour tous les polygones qui se projettent sur ce pixel, ou plus exactement la couleur du polygone en ce point. Pour cel, pour chaque facette du maillage, on parcourt tous les pixels de la projection de la facette (voir la gure 4.1), et on fait un test sur la profondeur z (dans le repre de la camra) pour savoir si un objet plus proche a dj t ach sur ce pixel.

35

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

Polygone P Projection du polygone P M

plan

de l

cran

Pixel (x, y) de la projection

Fig. 4.1: Principe de lalgorithme du zbuer Pour activer llimination des parties caches dans une application OpenGL sous Glut, il faut activer loption GLUT_DEPTH lors de lappel de glutInitDisplayMode : glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH); et activer le test de profondeur : glEnable(GL_DEPTH_TEST);

4.2

Sources de lumire et matriaux

Seulement si aucun objet plus proche na t ach, on stocke la couleur de la facette pour ce pixel dans le frame buer. Pour raliser les tests sur la profondeur, on doit stocker les profondeurs de tous les pixels dans un zbuer. Lachage (plus ou moins) raliste sous OpenGL repose sur une simulation simplie des clairages. Pour lutiliser, il faut dabord activer lclairage par glEnable(GL_LIGHTING);

4.2.1

Lumire ambiante

La lumire ambiante vient avec une mme intensit de toutes les directions, et elle est rchie par les objets dans toutes les directions avec une mme intensit. Un modle dillumination est traduit par une quation : lquation dclairement. Lquation dclairement pour la lumire ambiante sur un objet est de la forme : I = Ia ka o Ia est lintensit de la lumire ambiante, caractristique de la scne, et ka est un coecient entre 0 et 1, caractristique de lobjet considr. Pour rgler la lumire ambiante dans la scne, on peut utiliser la fonction glLightModelfv : 36

Chapitre 4 : clairage
N L

V 1111111111111111111111 0000000000000000000000 1111111111111111111111 0000000000000000000000 1111111111111111111111 0000000000000000000000 1111111111111111111111 0000000000000000000000

Fig. 4.2: Le vecteur normal et le vecteur dirig vers la source. GLfloat ambient_scene[] = {0.2, 0.2, 0.2, 1.0}; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient_scene); Les trois premiers coecients du vecteur sont les intensits en RGB de la lumire ambiante. Le quatrime coecient, appel alpha, est pour le moment ignor. On sen sert pour faire du apha-blending, par exemple pour faire des eets de transparence. Pour rgler les coecients de rexion de la lumire ambiante du matriau courant, on utilise glMaterialfv : GLfloat ambient[] = {0.2, 0.2, 0.2, 1.0}; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIANT, ambient); Le premier paramtre de glMaterialfv peut tre soit GL_FRONT, soit GL_BACK, soit GL_FRONT_AND_BACK. Cela permet de mettre un comportement dirent pour les faces selon leur orientation. Voir aussi le culling dans la section 2.3. Les trois premiers coecients du vecteurs sont les coecients de rexion de la lumire ambiante dans le rouge, vert et bleu.

4.2.2

Rexion diuse

Dans le cas dune source lumineuse ponctuelle non directionnelle, la rexion diuse tient compte, en un point dun objet, de la direction du vecteur N normal sortant lobjet en ce point, et de la direction du vecteur L dirig vers la source lumineuse (voir gure 4.2). I = IS krd cos si cos > 0 o IS est lintensit de la source lumineuse. Le coecient de rexion diuse krd est une caractristique de lobjet et varie entre 0 et 1. Pour dnir lintensit dune source lumineuse ponctuelle (pour le dius), on utilise glLightfv : GLfloat diffuse_light0[] = {1.0,1.0,1.0,1.0} glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_light0); Les trois premires coordonnes du vecteur sont les intensits dans le rouge, vert et bleu de la source. Il existe au moint 8 sources lumineuses (plus selon les implmentations dOpenGL) nommes GL_LIGHT0, GL_LIGHT1, GL_LIGHT2, etc... Il faut activer chaque source individuellement par glEnable(GL_LIGHT0); 37

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/


N

OpenGL

V R 1111111111111111111111 0000000000000000000000

1111111111111111111111 0000000000000000000000 1111111111111111111111 0000000000000000000000 1111111111111111111111 0000000000000000000000


Fig. 4.3: Le vecteur de la direction principale de rexion et de la direction de lobservateur.

(a) Lumire ambiante

(b) Rexion diuse

(c) Rexion spculaire

Fig. 4.4: Les direntes sortes de rexion. Ne pas oublier dactiver lclairage par glEnable(GL_LIGHTING). Pour rgler les coecients de rexion diuse du matriau courant, on utilise glMaterialfv : GLfloat diffuse[] = {0.2, 0.2, 0.2, 1.0}; glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse); Les trois premiers coecients du vecteurs sont les coecients de rexion diuse dans le rouge, vert et bleu.

4.2.3

Rexion spculaire

La rexion spculaire est un phnomne apparaissant sur les surfaces brillantes (voir la gure 4.4c). Considrons le vecteur R , symtrique de V par rapport N (voir gure 4.3). La direction R est la direction privilgie de rexion de la lumire vers lobservateur selon les lois de Descartes. Si la direction L de la source lumineuse est proche de la direction R , une lumire vive apparat lobservateur en ce point de lobjet. Le terme de lquation dclairement correspondant la rexion spculaire est couramment choisi proportionnel cosns (si < ), o est langle entre L et R et ns N . On peut 2 choisir une quation de la forme : Is = ks cosns o {R, G, B} et ks est le coecient de rexion spculaire, caractristique de lobjet, et variant entre 0 et 1. Lexposant ns sappelle lexposant spculaire, aussi appel brillance. Plus lexposant ns est lev, moins large est la tache claire lie la rexion spculaire (voir la gure 4.5). Pour dnir lintensit dune source lumineuse ponctuelle pour le spculaire, on utilise glLightfv : 38

Chapitre 4 : clairage

Fig. 4.5: Leet des coecients spculaires et brillance. Les coecients sont : en haut gauche ks = 0.2, ns = 5 ; en haut droite ks = 0.4, ns = 5 ; en bas gauche ks = 0.2, ns = 30 ; en bas droite ks = 0.4, ns = 30. GLfloat specular_light0[] = {1.0,1.0,1.0,1.0} glLightfv(GL_LIGHT0, GL_SPECULAR, specular_light0); Les trois premires coordonnes du vecteur sont les intensits dans le rouge, vert et bleu de la source. Pour rgler les coecients de rexion spculaire du matriau courant, on utilise glMaterialfv : GLfloat specular[] = {0.2, 0.2, 0.2, 1.0}; glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); glMaterialf((GL_FRONT_AND_BACK, GL_SHININESS, 110.0); Les trois premiers coecients du vecteurs sont les coecients de rexion specular dans le rouge, vert et bleu. La brillance (shininess) est lexposant spculaire. Dnas OpenGL, il est compris entre 0.0 et 128.0

4.2.4

Attnuation de la lumire avec la distance

Leet de la lumire sattnue avec la distance de lobjet considr la source lumineuse, et on modie frquemment le terme de lquation dclairement li aux rexions diuses et spculaires en multipliant par une fonction fatt . On peut par exemple prendre une fonction fatt de la forme : 1 fatt = min( , 1) c1 + c2 d L + c3 d 2 L o dL est la distance du point de lobjet considr la source lumineuse, et c1 , c2 et c3 sont choisis par lutilisateur, appels respectivement attnuation constante, attnuation linaire, et attnuation quadratique. Pour dnir les coecients dattnuation de la lumire avec la distance la source lumineuse, on utilise la fonction glLightf : glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 2.0); glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 1.0); glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.5); 39

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

Fig. 4.6: Eet de lattnuation de la lumire avec la distance sur des sphres de mme coecient de rexion diuse. Les sphres sont une distance la source lumineuse de 302 (en haut gauche et en bas droite), 177 (en haut droite), et 389 (en bas gauche). Les coecients dattnuation sont de c1 = 0.1, c2 = 5.105, c3 = 7.105. Les valeurs doivent tre adaptes suivant les dimensions de la scne clairer.

4.2.5

Spots

Jusqu prsent, nous navons tudi que des sources non directionnelles, cest dire que la lumire issue dune telle source part de la mme manire dans toutes les directions. En ralit, les sources de lumire, tels des spots, mettent souvent de la lumire dans une direction privilgie. Cela correspond au modle de source lumineuse de type spot.

4.3

Vecteurs normaux

Pour calculer les termes de rexion diuse et spculaire, OpenGL a besoin de connatre les vecteurs normaux (vecteurs orthogonaux la surface) aux sommets du maillage. Ces vecteurs normaux peuvent tre calculs et mmoriss lors de la construction du maillage partir dun modle analytique de surface, ou bien il peut tre estim sur le maillage. Pour estimer la normale sur un maillage, on fait pour chaque sommet une moyenne des normales incidentes au sommet. Une fois les normales connues, on peut les communiquer OpenGL en utilisant la fonction glNormal3f avant un appel glVertex3f lors du dessin dune primitive gomrique. Par exemple, on peut indiquer les normales aux sommet dun triangle comme suit : On doit tout dabord appeler glEnable(GL_NORMALIZE) qui assure que les vecteurs normaux sont normaliss (de longuer 1), en calculant la norme du vecteur normal et en divisant ses coordonnes par la norme. Cest dautant plus utile si lon eectue des transformation de type changement dchelle (glScalef). Ensuite, on appelle glNormal3f avant chaque dnition de sommet : glBegin(GL_TRIANGLES); glNormal3f(1.0,2.0,3.0); /* Ce vecteur doit tre normalis */ glVertex3f(0.0, 1.0, 0.0); glNormal3f(2.0,1.0, 3.0); 40

Chapitre 4 : clairage glVertex3f(1.0, 0.0, 0.0); glNormal3f(1.0,1.0, 2.0); glVertex3f(0.0, 0.0, 0.5); glEnd();

4.4

clairement plat et lissage de Gouraud

Lalgorithme dlimination des partie caches utilis par OpenGL, appel zbuer, utilise une approximation des tous les objets par des maillages. Si lon visualise directement un tel maillage, des facettes sont visibles (voir la gure 4.7). Prendre des facettes diminue les performances et nest pas vraiment envisageable. Aussi prfre-t-on en gnral faire des interpolations pour lisser lintensit lumineuse sur la surface. Pour cel, OpenGL propose un achage par le modle de Gouraud, dans lequel ine interpolation bilinaire est eectue partir des intensits des sommet .

(a) clairement plat GL_FLAT

(b) Lissage de Gourand GL_SMOOTH

Fig. 4.7: La fonction glShadeModel permet de slectioner lclairement plat ou le lissage de Gouraud Pour slectionner lclairement plat : glShadeModel(GL_FLAT); Pour slectionner lclairement liss de Gouraud : glShadeModel(GL_SMOOTH);

4.5

Grer la position et direction des sources lumineuses

Pour dnir la position dune source lumineurs GL_LIGHT0, GL_LIGHT1, etc. on utilise la fonction glLightfv. Par exemple, pour placer la source GL_LIGHT0 en position (5, 10, 7) 41

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

/* Exemple de source place en (5,10,7) */ GLfloat lightPosition0[] = {5.0,10.0,7.0,1.0}; ... glLightfv(GL_LIGHT0, GL_POSITION, lightPosition0); Les coordonnes de la position de la source sont des coordonnes homognes. On peut dnir une source place linni en dnissant la quatriemme coordonne w gale 0. /* Exemple de source place linfini le long de laxe des x */ GLfloat lightPosition0[] = {1.0,0.0,0.0,0.0}; ... glLightfv(GL_LIGHT0, GL_POSITION, lightPosition0); Les sources places linni (comme le soleil) projettent des rayons lumineux parallles dans la scne. La position de la source est multiplie par la matrice GL_MODELVIEW courante. (la matrice GL_PROJECTION na pas deet sur la position dune source lumineuse). On peut donc, suivant le point dans le code o lon dnit la postion de la source, positioner la source ou bien dans le repre du monde ou bien dans le repre de la camra. Exemple 1. Source xe dans le repre de la camra. Pour faire une source lumineuse xe dans le repre de la camra, il faut dnir la position de la source dans le code juste aprs linitialisation de la matrice GL_MODELVIEW. Dans lexemple suivant, la source est positionne prcisment linni le long de laxe de vise, derire lobservateur (voir la gure 4.8).

(a) Exemple 1

(b) Exemple 2

Fig. 4.8: Dans lexemple 1, la source est place sur laxe de vise du repre de la camra. Dans lexemple 2, la source subit la transformation gluLookAt et se trouve dans le repre de la thire sur laxe des z

#include <GL/glut.h> #include <stdio.h> #include <stdlib.h> GLushort largeur_fenetre=500; 42

Chapitre 4 : clairage GLushort hauteur_fenetre=500; void Redimensionnement(int l,int h) { GLfloat lightPosition0[] = {0.0,0.0,10.0,0.0}; GLfloat diffuseLight0[] = {0.6,0.6,0.6,1.0}; GLfloat specularLight0[] = {0.6,0.6,0.6,1.0}; largeur_fenetre = l; hauteur_fenetre = h; glViewport(0,0,(GLsizei)largeur_fenetre,(GLsizei)hauteur_fenetre); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(20,l/(GLdouble)h, 0.01, 10000); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glLightfv(GL_LIGHT0,GL_DIFFUSE, diffuseLight0); glLightfv(GL_LIGHT0,GL_SPECULAR, specularLight0); glLightfv(GL_LIGHT0, GL_POSITION, lightPosition0); } void Affichage(void ) { GLfloat diffuse[] = {1.0,1.0,1.0,1.0}; GLfloat specular[] = {1.0,1.0,1.0,1.0}; GLfloat ambient[] = {0.2,0.2,0.2, 1.0}; GLfloat shininess = 110.0; glClearColor(1.0,1.0,1.0,1.0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glPushMatrix(); gluLookAt(8, 10, 15, /* rglage de la camra */ 0,0,0, 0,1,0); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,specular); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient); glutSolidTeapot(2); /* dessin dune thire */ glPopMatrix(); glutSwapBuffers(); /* Envoyer le buffer lcran */ } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH); glutInitWindowPosition(100,100); 43

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

glutInitWindowSize(largeur_fenetre,hauteur_fenetre); glutCreateWindow("Source place linfini derire lobservateur"); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); glShadeModel(GL_SMOOTH); glutDisplayFunc(Affichage); glutReshapeFunc(Redimensionnement); glutMainLoop(); return 0; } Exemple 2. Source place dans le repre du monde #include <GL/glut.h> #include <stdio.h> #include <stdlib.h> GLushort largeur_fenetre=500; GLushort hauteur_fenetre=500; void Redimensionnement(int l,int h) { largeur_fenetre = l; hauteur_fenetre = h; glViewport(0,0,(GLsizei)largeur_fenetre,(GLsizei)hauteur_fenetre); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(20,l/(GLdouble)h, 0.01, 10000); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void Affichage(void ) { GLfloat lightPosition0[] = {0.0,0.0,10.0,0.0}; GLfloat diffuseLight0[] = {0.6,0.6,0.6,1.0}; GLfloat specularLight0[] = {0.6,0.6,0.6,1.0}; GLfloat diffuse[] = {1.0,1.0,1.0,1.0}; GLfloat specular[] = {1.0,1.0,1.0,1.0}; GLfloat ambient[] = {0.2,0.2,0.2, 1.0}; GLfloat shininess = 110.0; glClearColor(1.0,1.0,1.0,1.0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glPushMatrix(); 44

Chapitre 4 : clairage gluLookAt(8, 10, 15, /* rglage de la camra */ 0,0,0, 0,1,0); glLightfv(GL_LIGHT0,GL_DIFFUSE, diffuseLight0); glLightfv(GL_LIGHT0,GL_SPECULAR, specularLight0); glLightfv(GL_LIGHT0, GL_POSITION, lightPosition0); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,specular); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient); glutSolidTeapot(2); /* dessin dune thire */ glPopMatrix(); glutSwapBuffers(); /* Envoyer le buffer lcran */ } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH); glutInitWindowPosition(100,100); glutInitWindowSize(largeur_fenetre,hauteur_fenetre); glutCreateWindow("Source place linfini derire lobservateur"); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); glShadeModel(GL_SMOOTH); glutDisplayFunc(Affichage); glutReshapeFunc(Redimensionnement); glutMainLoop(); return 0; }

45

Chapitre 5 Aspects avancs du rendu


5.1
5.1.1

Optimisation de lachage : Vertex Arrays


Quest-ce quun Vertex Array ?

Lorsquon dessine un maillage, il peut y avoir un trs grand nombre de fonctions, avec pour chaque sommet un appel de glVertex3f, un appel de glNormal3f, ventuellement glColor3f, etc. (voir lexemple 1 version 1 dachage de ttradre ci-dessous). En outre, chaque sommet peut tre traits plusiers fois, indpendament pour chaque face incidente. Les Vertex Arrays permettent de dnir tous les sommets et leur donnes telles que les normales, couleur, etc. en utilisant quelques tableaux. Lachage ne ncessite alors plus de lister les sommets. Les tableaux concernant les sommets sont envoys une fois en mmoire graphique et utiliss directement par OpenGL pour lachage. Les facettes sont dcrites par des indices de sommets dans les tableaux.

5.1.2

Exemple : achage dun ttradre

Exemple 1. Version 1 Achage non optimis dun ttradre. Le code suivant ache un ttradre dont les sommets ont direntes couleurs (voir la gure 5.1). (Les couleurs sont interpoles lintrieur des facettes du ttradre).

Fig. 5.1: Achage dun ttradre avec des sommets de direntes couleurs. 46

Chapitre 5 : Aspects avancs du rendu

#include <GL/glut.h> #include <stdio.h> #include <stdlib.h> GLushort largeur_fenetre=500; GLushort hauteur_fenetre=500; GLint nvertices=4, nfaces=4; GLfloat vertices[] = { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 }; GLfloat colors[] = { 0.0, 0.0, 0.0, 0.7, 0.5, 0.2, 0.5, 0.7, 0.9, 0.6, 1.0, 0.6 }; GLuint faces[] = { 0, 1, 2, 0, 1, 3, 0, 2, 3, 1, 2, 3 }; void Redimensionnement(int l,int h) { largeur_fenetre = l; hauteur_fenetre = h; glViewport(0,0,(GLsizei)largeur_fenetre,(GLsizei)hauteur_fenetre); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(20,l/(GLdouble)h, 0.01, 10000); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void DessinTetraedre() { int i, j; 47

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

glBegin(GL_TRIANGLES); for (i=0 ; i<3*nfaces ; i++) { glColor3fv(&colors[3*faces[i]]); glVertex3fv(&vertices[3*faces[i]]); } glEnd(); } void Affichage(void ) { glClearColor(1.0,1.0,1.0,1.0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(-0.2,-0.2,-4); glRotatef(-30, 1.0, 0.0, 0.0); glRotatef(120, 0.0, 1.0, 0.0); DessinTetraedre(); glPopMatrix(); glutSwapBuffers(); /* Envoyer le buffer lcran */ } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH); glutInitWindowPosition(100,100); glutInitWindowSize(largeur_fenetre,hauteur_fenetre); glutCreateWindow("Dessin dun ttradre"); glEnable(GL_DEPTH_TEST); glutDisplayFunc(Affichage); glutReshapeFunc(Redimensionnement); glutMainLoop(); return 0; } Exemple 1. Version 2 Achage dun ttradre avec Vertex Arrays. Limage obtenue par cette verion est la mme que pour la version 1. Le code de lachage du maillage ne comprend quun seul appel de fonction. #include <GL/glut.h> #include <stdio.h> #include <stdlib.h> GLushort largeur_fenetre=500; GLushort hauteur_fenetre=500; 48

Chapitre 5 : Aspects avancs du rendu

GLint nvertices=4, nfaces=4; GLfloat vertices[] = { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 }; GLfloat colors[] = { 0.0, 0.0, 0.0, 0.7, 0.5, 0.2, 0.5, 0.7, 0.9, 0.6, 1.0, 0.6 }; GLuint faces[] = { 0, 1, 2, 0, 1, 3, 0, 2, 3, 1, 2, 3 }; /* mettre des UNSIGNED INT */

void Redimensionnement(int l,int h) { largeur_fenetre = l; hauteur_fenetre = h; glViewport(0,0,(GLsizei)largeur_fenetre,(GLsizei)hauteur_fenetre); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(20,l/(GLdouble)h, 0.01, 10000); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void DessinTetraedre() { glDrawElements(GL_TRIANGLES, 3*nfaces, GL_UNSIGNED_INT, faces); } void Affichage(void ) { glClearColor(1.0,1.0,1.0,1.0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glPushMatrix(); 49

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

glTranslatef(-0.2,-0.2,-4); glRotatef(-30, 1.0, 0.0, 0.0); glRotatef(120, 0.0, 1.0, 0.0); DessinTetraedre(); glPopMatrix(); glutSwapBuffers(); /* Envoyer le buffer lcran */ } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH); glutInitWindowPosition(100,100); glutInitWindowSize(largeur_fenetre,hauteur_fenetre); glutCreateWindow("Dessin dun ttradre : version rapide"); glEnable(GL_DEPTH_TEST); glutDisplayFunc(Affichage); glutReshapeFunc(Redimensionnement); /* Activation des Vertex Array et Color Array */ glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); /* Chargement du Color Array */ glColorPointer(3, GL_FLOAT, 0, colors); /* Chargement du Vertex Array */ glVertexPointer(3, GL_FLOAT, 0, vertices); glutMainLoop(); return 0; }

5.1.3

Principe gnral

On peut aussi mettre dans un Normal Array les normales aux sommets, les coordonnes de texture, etc. Pour activer les Arrays, on utilise la fonction void glEnableClientState(GLenum array); qui peut prendre comme paramtreGL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_NORMAL_ARRAY, GL_TEXTURE_COORD_ARRAY... On dsigne ladresse o se trouvent les sommets, normales, couleurs, etc. en utilisant les fonctions void glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); 50

Chapitre 5 : Aspects avancs du rendu void glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); void glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer); void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); Les paramtres sont : size, qui vaut 2, 3 ou 4 et donne le combre de composantes pour chaque sommet. Une normale a toujours 3 composantes donc ce paramtre est absent de glNormalPointer. type peut valoir suivant le type de donnes GL_FLOAT, GL_DOUBLE, GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT. stride donne le nombre doctets entre deux donnes conscutives (nombre de composantes multipli par le nombre doctets par composante), sachant quil peut y avoir des lespace occup par dautre donnes entre deux sommets. Ceci permet par exemple de mettre les sommets et les normales dans un mme tableau. Si le paramtre stride vaut 0, les donnes sont supposes contiges (sans espace entre deux donnes). pointer donne ladresse dun tableau contenant les donnes. Pour lachage, on prsente ici la fonction glDrawElements qui peut acher des maillages dont les sommets sont toutes de mme type (triangles, ou quads,...). Dautres fonctions existent, telles que glDrawElement qui permet de grer la main quels sommets sont achs, et glMultiDrawElements qui permet dacher des maillages dont les faces peuvent avoir des nombres de sommets dirents les une des autres. La fonction glDrawElements a pour prototype : void glDrawElements(GLenum mode, GLsizei count, GLenum type, void *indices); Les paramtres ont la signication suivante : mode est lun des arguments valides de glBegin et dcrit le type de primitive gomtrique ache. Il peut tre GL_TRIANGLES, GL_QUADS, GL_POLYGON, GL_LINES, GL_POINTS, etc. count est le nombre total dlments tracs (somme des nombre de sommets des faces). type dcrit le type entier dans lequel sont donns les indices des sommets dans les faces. Il peut tre GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, ou GL_UNSIGNED_INT. On peut compresser le tableau des indices en utilisant GL_UNSIGNED_BYTE mais il faut alors sassurer que les indices des sommets sont infrieurs 256. indices est le tableau comprenant les indices. On met les indices de toutes les faces la suite. Ceci est cohrent avec le comportement de lachage de primitives gomtriques, qui permet par exemple de dessiner plusieurs triangle en passant tous les sommets entre le glBegin(GL_TRIANGLES) et le glEnd(). Pour dessiner des maillages dont toutes les faces ne comportent pas le mme nombre de sommet, on utilise : void glMultiDrawElements(GLenum mode, const GLsizei * count, GLenum type, const GLvoid ** indices, GLsizei primcount); 51

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

(a) Image de texture

(b) Rendu de sphre texture

(c) Objets texturs

Fig. 5.2: Exemple de plaquage de texture Le paramtre count donne un tableau avec pour chaque face le nombre de sommets de la face, primcount donne le nombre de faces, et indices donne un tableau de tableaux dindices de sommets.

5.2
5.2.1

Plaquage de textures
Principe du plaquage de texture

Le but du plaquage de texture est de reprsenter des objets qui nont pas une couleur uniforme (voir gures 5.2). De tels objets sont trs courants dans le rel, leur reprsentation est donc essentielle en synthse dimages. Le principe du plaquage de textures consiste plaquer une image plane, appele image de texture, sur la surface de lobjet. Par exemple, lobjet de la gure 5.2b a t obtenu en plaquant limage de la gure 5.2a sur une sphre. Pour cela, tant donn un point M de la surface, il faut faire correspondre au point M un point T (M) de limage de texture. La couleur de lobjet au point M prendre en compte pour lachage est alors la couleur de limage de texture au point T (M). Les coordonnes du point T (M) dans le plan sappellent les coordonnes de texture du point M. En gnral, on associe au point M des coordonnes s(M) et t(M) dans [0, 1]. Par exemple, dans le cas dune sphre, on fait correspondre un point M un point dune image suivant la latitude et longiture. (voir gure 5.3). Notons que les changements dchelle sur les axes permettent de ramener lintervalle [0, 2] o varie langle sur lintervalle [0, largeur 1]. Il en va de mme pour lintervalle o varie langle avec la hauteur. Plus gnralement, soit : [0, 1] [0, 1] R3 une surface paramtre, et soit une image de texture de dimensions largeur hauteur. On peut faire correspondre au point M = (s, t) de la surface les coordonnes s(M) = s et t(M) = t, on obtient donc le point T (M) = (s.largeur, t.hauteur) dans limage de texture. 52

Chapitre 5 : Aspects avancs du rendu

S
(a) Le point M sur la sphre

(b) Le point correspondant dans limage de texture

(c) Latitude et longitude sur la sphre

Fig. 5.3: Correspondance Surface - Image de texture.

53

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

5.3

Plaquage de textures avec OpenGL

Exemple 1. Gnration de texture par un algorithme puis plaquage de la texture. La fonction CreeBitmap gnre les couleurs des texels (les texels sont lquivalent des pixels dans une image de texture). Les donnes de textels sont stocks dans un grand tableau qui contient les lignes les unes la suite des autres. La couleur de chaque texel est socke sur 4 octets par ses composantes RGBA.

(a) Image de texture gnre

(b) Quadrilatre textur vu en perspective

#include <GL/glut.h> #include <stdio.h> #include <stdlib.h> #dene largeur_tex 128 #dene hauteur_tex 128 GLushort largeur_fenetre=500; GLushort hauteur_fenetre=500; GLint angle=0; GLuint id = 0; /* texture ID */

/* bitmap contenant les couleurs RGBA de la texture */ GLubyte image_tex[largeur_tex*hauteur_tex*4]; void CreeBitmap() { 54

Chapitre 5 : Aspects avancs du rendu int i, j; GLubyte r, g, b; for (i=0 ; i<hauteur_tex ; i++) { for (j=0 ; j<largeur_tex ; j++) { r = (i*32)%256; g = (j*32)%256; b = ((i*16)*(j*16))%256; image_tex[(i*largeur_tex+j)*4] image_tex[(i*largeur_tex+j)*4+1] image_tex[(i*largeur_tex+j)*4+2] image_tex[(i*largeur_tex+j)*4+3] } } } void CreeTexture2D(void ) { struct gl_texture_t *png_tex = NULL; CreeBitmap(); /* Generation texture */ glGenTextures(1, &id); glBindTexture(GL_TEXTURE_2D, id); /* Paramtres de filtres linaires */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); /* Cration de la texture */ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, largeur_tex, hauteur_tex, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_tex); } void Affichage(void ) { glClearColor(1.0,1.0,1.0,1.0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glPushMatrix(); gluLookAt(8, 10, 15, /* rglage de la camra */ 0,0,0, 0,1,0); glRotatef(0.05*angle, 0.0, 1.0, 0.0);

= = = =

r; g; b; 255;

55

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

glBindTexture (GL_TEXTURE_2D, id); /* slection de la texture */ glEnable (GL_TEXTURE_2D); /* activation des textures */ glBegin(GL_QUADS); glTexCoord2f(0.0,0.0); glTexCoord2f(1.0,0.0); glTexCoord2f(1.0,1.0); glTexCoord2f(0.0,1.0); glEnd();

glVertex3f(-3.0,-2.0,0.0); glVertex3f(3.0,-2.0,0.0); glVertex3f(3.0,2.0,0.0); glVertex3f(-3.0,2.0,0.0);

glDisable (GL_TEXTURE_2D); /* dsactivation des textures */ glPopMatrix(); glutSwapBuffers(); } void Redimensionnement(int l,int h) { largeur_fenetre = l; hauteur_fenetre = h; glViewport(0,0,(GLsizei)largeur_fenetre,(GLsizei)hauteur_fenetre); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(20,l/(GLdouble)h, 0.01, 10000); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void IdleFonction(void ) { angle++; glutPostRedisplay(); } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH); glutInitWindowPosition(100,100); glutInitWindowSize(largeur_fenetre,hauteur_fenetre); glutCreateWindow("Source place linfini derire lobservateur"); glEnable(GL_DEPTH_TEST); glutDisplayFunc(Affichage); glutReshapeFunc(Redimensionnement); glutIdleFunc(IdleFonction); CreeTexture2D(); 56

/* Envoyer le buffer lcran */

Chapitre 5 : Aspects avancs du rendu

glutMainLoop(); return 0; } Les principales fonctions utilises ici sont : void glGenTextures(GLsizei n, GLuint *textureNames); Gnre n identiants de textures non utiliss et le met dans textureNames. void glBindTexture(GLenum target, GLuint textureName); Permet trois choses : Dactiver (par un identiant obtenu par glGenTextures) une texture pour lutiliser, par exmple dans un achage ; De crer une nouvelle texture si la texture na pas encore t utilise ; De dsactiver lutilisation des textures si lon passe 0 comme identiant de texture. void glDeleteTextures(GLsizei n, const GLuint *textureNames); Libre la mmoire et les identiants coorespondant aux textures dont les noms sont passs dans le tableau textureNames. void glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); Dnit une texture 2D. On spcie la largeur, hauteur, et les couleurs des pixels, et la texture prcdement slectionne par glBindTexture est initialise avec ces pixels. Le format interne indique lesquelles des composantes R,G,B,A, luminance ou intensits seront utilises par OpenGL pour dcrire les texels de limage. Il y a trente 38 constantes possibles pour le format, qui peut aussi spcier le nombre doctets utiliss pour chaque composante. Les valeurs les plus simples sont GL_RGB, GL_RGBA, GL_LUMINANCE ou encore GL_ALPHA pour le alpha-blending. Ces valeurs peuvent aussi tre utilises pour la variable format qui dcrit le format du tableau pixels. void glTexCoord2f(GLfloat s, GLfloat t); Attribue les coordonnes de texture (s, t) au(x) prochain(s) sommet(s) cr avec glVertex*(). void glTexParameteri(GLenum target, GLenum pname, TYPE param); 57

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

Permet de slectionner des modes dutilisation de texture. On peut par exemple crer des textures cycliques avec pname gal GL_TEXTURE_WRAP_S ou GL_TEXTURE_WRAP_T et param gal GL_REPEAT. Avec le paramtre pname gal GL_TEXTURE_MAG_FILTER ou GL_TEXTURE_MIN_FILTER, on dnit comment les couleurs de textures sont interpoles lorsquun pixel de lcran ne correspond pas exactement un pixel de limage de texture (ce qui est gnralement le cas). Exemple 2. Plaquage de texture sur une sphre. La texture est charge partir dun chier PNG. On ne dcrit pas ici le chargement de chier PNG mais on suggre dutiliser par exemple la librairie Open Source libpng. La sphre est ache en tant que quadrique, ce qui permet de gnrer automatiquement des coordonnes de textures (contrairement glutSolidSphere). La technique des quadriques permet aussi dacher des cnes, cylindres, parabolodes, etc.

(a) Fichier PNG (extrait)

(b) Sphre texture

#include #include #include #include

<GL/glut.h> <stdio.h> <stdlib.h> <my_png_lib.h> /* utiliser une librairie comme libpng */

GLushort largeur_fenetre=500; GLushort hauteur_fenetre=500; GLint angle=0; GLuint id = 0; /* texture ID */

void ChargeTexturePNG(const char *fichier) { struct gl_texture_t *png_tex = NULL;

58

Chapitre 5 : Aspects avancs du rendu /* Lecture du fichier PNG et initialisation dun bitmap */ LirePNG(fichier, &largeur, &hauteur, &texels); /* (voir librairies Open Source libpng, liblpg,...) */ /* Generation texture */ glGenTextures(1, &id); glBindTexture(GL_TEXTURE_2D, id); /* Paramtres de filtres linaires */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); /* Cration de la texture */ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, largeur, hauteur, 0, GL_RGB, GL_UNSIGNED_BYTE, png_tex->texels); free(texels); } void Affichage(void ) { GLUquadricObj *quadrique; GLfloat diffuse[] = {1.0,1.0,1.0,1.0}; GLfloat specular[] = {1.0,1.0,1.0,1.0}; GLfloat ambient[] = {0.2,0.2,0.2, 1.0}; GLfloat shininess = 110.0; glClearColor(1.0,1.0,1.0,1.0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glPushMatrix(); gluLookAt(8, 10, 15, /* rglage de la camra */ 0,0,0, 0,1,0); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,specular); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient); glRotatef(0.05*angle, 0.0, 1.0, 0.0); glBindTexture (GL_TEXTURE_2D, id); /* slection de la texture */ glEnable (GL_TEXTURE_2D); /* activation des textures */ quadrique = gluNewQuadric(); /* cration dune quadrique */ /* initialisation des coordonnes de texture : */ gluQuadricTexture(quadrique, GL_TRUE); gluQuadricNormals(quadrique, GLU_SMOOTH); /* init normales */ 59

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

gluSphere(quadrique, 2, 128 , 64); /* dessin dune sphre */ glDisable (GL_TEXTURE_2D); /* dsactivation des textures */ glPopMatrix(); glutSwapBuffers(); } void Redimensionnement(int l,int h) { GLfloat lightPosition0[] = {0.0,0.0,10.0,0.0}; GLfloat diffuseLight0[] = {0.6,0.6,0.6,1.0}; GLfloat specularLight0[] = {0.6,0.6,0.6,1.0}; largeur_fenetre = l; hauteur_fenetre = h; glViewport(0,0,(GLsizei)largeur_fenetre,(GLsizei)hauteur_fenetre); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(20,l/(GLdouble)h, 0.01, 10000); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glLightfv(GL_LIGHT0,GL_DIFFUSE, diffuseLight0); glLightfv(GL_LIGHT0,GL_SPECULAR, specularLight0); glLightfv(GL_LIGHT0, GL_POSITION, lightPosition0); } void IdleFonction(void ) { angle++; glutPostRedisplay(); } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH); glutInitWindowPosition(100,100); glutInitWindowSize(largeur_fenetre,hauteur_fenetre); glutCreateWindow("Source place linfini derire lobservateur"); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glShadeModel (GL_SMOOTH); glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); glShadeModel(GL_SMOOTH); glutDisplayFunc(Affichage); glutReshapeFunc(Redimensionnement); 60

/* Envoyer le buffer lcran */

Chapitre 5 : Aspects avancs du rendu glutIdleFunc(IdleFonction); /* Chargement de la texture partir du fichier PNG */ /* pass en argument */ if (argc != 2) { fprintf(stderr, "Usage : %s fichier.png\n", argv[0]); exit(0); } ChargeTexturePNG(argv[1]); glutMainLoop(); return 0; }

61

Annexe A Aide mmoire dopenGL


A.1 Types

GLushort /* unsigned short : entier non sign sur 2 octets */ GLint /* entier sign su 4 octets */ GLfloat /* nombre flottant simple prcision sur 4 octets */ GLdouble /* nombre flottant double prcision sur 8 octets */ GLubyte /* octet non sign (0,...,255) */

A.2
A.2.1

vennements, GLUT
Fentre

/* initialisation et cration dune fentre */ /* rglage de la taille initiale de la fentre */ glutInitWindowSize (GLushort sx, GLushort sy); /* rglage de la position initiale de la fentre */ glutInitWindowPosition (GLushort px, GLushort py); /* cration de la fentre avec un titre */ glutCreateWindow (char *titre); /* Evennement de redimensionnement de la fentre */ void glutReshapeFunc(void (*func)(GLushort, GLushor));

A.2.2

Initialisation du mode dachage

glutInitDisplayMode(GLint masque); GLUT_RGB /* mode RGB */ GLUT_RGBA; /* mode RGBA avec transparence */ GLUT_DEPTH /* avec buffer de profondeur */ GLUT_SINGLE /* pour application avec image fixe */ GLUT_DOUBLE /* avec double buffer pour animations */ glEnable(GL_DEPTH_TEST); /* permet llimination des parties caches */ 62

Chapitre A : Aide mmoire dopenGL glEnableGL_CULL_FACE; /* active le culling (limination de faces) */ glutMainLoop(); /* boucle dattente des vennements */

A.2.3

vennements

/* dclaration dune fonction daffichage : */ void glutDisplayFunc(void (*func)(void)); /* pour provoquer un affichage */ void glutPostRedisplay(void); /* dclaration dune fonction de redimensionnement de la fentre : */ void glutReshapeFunc(void (*func)(int, int)); /* (les deux int sont les nouvelles dimensions de la fentre) */ /* dclaration dune fonction timer pour les aniamtions */ void glutIdleFunc(void (*func)(void)); /* dclaration dune fonction de tratement des saisies clavier : */ void glutKeyboardFunc(void (*func)(unsigned char key, int x, int y)); /* lunsigned char est la touche prsse */ /* x et y donnent les coordonnes de la position de la souris */ /* dclaration dune fonction de saisie des touches spciales : */ void glutSpecialFunc(void (*func)(int key, int x, int y)); /* le paramtre key est la touche prsse */ /* x et y donnent les coordonnes de la position de la souris */ /* touches spciales pour les flches au clavier */ GLUT_KEY_LEFT, GLUT_KEY_RIGHT, GLUT_KEY_UP, GLUT_KEY_DOWN /* dclaration dune fonction de gestion des clicks de souris : */ void glutMouseFunc(void (*func)(int button, int state, int x, int y)); /* valeurs possible du paramtre button : */ GLUT_LEFT_BUTTON, GLUT_RIGHT_BUTTON, GLUT_MIDDLE_BUTTON /* valeurs possibles du paramtre state : */ GLUT_DOWN, GLUT_UP /* x et y donnent les coordonnes de la position de la souris */ /* dclaration dune fonction de gestion du mouvement de la souris */ /* avec au moins un bouton de la souris enfonc */ void glutMotionFunc(void (*func)(int x, int y)); /* x et y donnent les coordonnes de la position de la souris */ /* dclaration dune fonction de gestion du mouvement de la souris */ /* sans aucun bouton de la souris enfonc */ void glutPassiveMotionFunc(void (*func)(int x, int y)); 63

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

/* x et y donnent les coordonnes de la position de la souris */

A.2.4

Menus

/* associer un menu une fonction : */ /* la fonction prend en paramtre */ /* le numro de la commande de menu */ /* actionne par lutilisateur */ /* (faire un switch) */ int glutCreateMenu(void (*func)(int value)); /* ajouter une commande un menu */ /* avec un numro de commande : */ void glutAddMenuEntry(char *name, int value); /* Attacher le dernier menu dfini la pression */ /* dun bouton de la souris */ void glutAttachMenu(int button); /* rappel : */ GLUT_LEFT_BUTTON GLUT_MIDDLE_BUTTON GLUT_RIGHT_BUTTON /* ajouter un sous-menu un menu */ void glutAddSubMenu(char *entryName, int menuIndex);

A.3

Couleur

glClearColor(GLfloat, GLfloat, GLfloat); /* slectioner la couleur du fond */ glClear(int masque); /* faage de certains buffers (cran, z-buffer,...) */ GL_COLOR_BUFFER_BIT; /* masque pour le buffer de couleurs (image) */ GL_DEPTH_BUFFER_BIT /* masque pour le buffer de profondeur (z-buffer) */ glColor3f(GLfloat, GLfloat, GLfloat); /* slectioner une couleur RGB */ glColor4f(GLfloat, GLfloat, GLfloat, GLfloat); /* slectioner une couleur RGBA */

A.4

Paramtres de la camra

/* Positionnement du repre de la camra sur la position pos, dirige vers centre, avec le vecteur up vertical sur la vue */ void gluLookAt(GLdouble posX, GLdouble posY, GLdouble posZ, GLdouble centreX, GLdouble centreY, GLdouble centreZ, GLdouble upX, GLdouble upY, GLdouble upZ); /* Rglage des paramtres de la projection 3D->2D, angle douverture, ratio L/H, cliping plane proche et loign */ void gluPerspective(GLdouble angleOuvertureY, GLdouble aspect, GLdouble zNear, GLdouble zFar); 64

Chapitre A : Aide mmoire dopenGL /* Rglage de la position et dimention de la fentre graphique en 2D (coordonnes 2D virtuelles) */ void glViewport(GLint x, GLint y, GLsizei largeur, GLsizei hauteur);

A.5

Position, transformations, rotations

glMatrixMode(int); /* passage dans un mode donn */ GL_PROJECTION /* mode projection */ GL_MODELVIEW /* mode modelview */ glLoadIdentity(); /* rinitialisation de la matrice dans un mode fix */ /* translation dun vecteur v : */ void glTranslatef(GLfloat vx, GLfloat vy, GLfloat vz); /* changements dchelle sur les trois axes : */ void glScalef(GLfloat facteurx, GLfloat facteury, GLfloat facteurz); rotation vectorielle autour dune droite de vecteur directeur v void glRotatef(GLfloat angle, GLfloat vx, GLfloat vy, GLfloat vz); glPushMatrix(); glPopMatrix(); /* empiler une matrice pour la restorer plu tard */ /* dpiler une matrice pour restorer celle du dessous */

A.6

Sommets

glVertex3f(GLfloat, GLfloat, GLfloat); /* dessiner un sommet */ glVertex3d(GLdouble, GLdouble, GLdouble); /* dessiner un sommet */ glVertex3dv(GLdouble[]); /* dessiner unsommet */

A.7

Points, segments, polygones

glBegin(XXX); glEnd(); GL_POINTS /* dessiner des points */ GL_LINES /* dessiner des segments entre paires de sommets */ GL_LINE_STRIP /* dessiner une ligne brise */ GL_LINE_LOOP /* dessiner une ligne brise ferme */ GL_POLYGON /* dessiner un polygone convexe */ GL_QUADS GL_QUAD_STRIP GL_TRIANGLES GL_TRIANGLE_STRIP GL_TRIANGLE_FAN glRectf(GLfloat, GLfloat, GLfloat, GLfloat); /* dessiner un rectangle */ 65

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

/* rgler lpaisseur du trait */ void glPointSize(GLfloat); /* paisseur dun point */ void glLineWidth(GLfloat); /* paisseur des lignes */ /* antialiassage */ glEnable(GL_LINE_SMOOTH); glEnable(GL_POLYGON_SMOOTH); /* pointills sur des droites */ glEnable(GL_LINE_STIPPLE); glLineStipple (GLint, GLushort); /* Stries sur un polygone */ glEnable(GL_POLYGON_STIPPLE); glPolygonStipple(GLubyte *)

A.8

Dessin, formes

/* Dessiner un cube : */ /* faire des changements dchelle pour obtenir un paralllpipde */ glutWireCube(GLfloat taille); glutSolidCube(GLfloat taille); /* dessiner une sphre : */ /* faire des changements dchelle pour obtenir un ellipsode */ glutWireSphere(GLfloat, int nbre_paralleles, int nbre_meridiens); glutSolidSphere(GLfloat, int nbre_paralleles, int nbre_meridiens); /* dessiner une thire : */ glutSolidTeapot(GLdouble taille); glutWireTeapot(GLdouble taille ); /* dessiner une quadrique : */ /* obtenir un pointeur de quadrique */ GLUquadricObj* gluNewQuadric(void); /* dessiner un disque : */ void gluDisk(GLUquadricObj*, GLfloat, GLfloat,GLint,GLint); /* librer le pointeur de quadrique aprs utilistion : */ void gluDeleteQuadric(GLUquadricObj*); /* Dessiner un caractre lcran */ void glutStrokeCharacter(void *font, int character); GLUT_STROKE_ROMAN 66

Chapitre A : Aide mmoire dopenGL

A.9

Achage 3D et clairage

/* Activer laffichage z-buffer avec clairage */ glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); /* Proprits de rflexion des matriaux */ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIANT, vector); GL_FRONT_AND_BACK, GL_FRONT, GL_BACK GL_AMBIANT, GL_DIFFUSE, GL_SPECULAR glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, value); /* Sources lumineuses */ GL_LIGHT0, GL_LIGHT1, GL_LIGHT2... glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0, GL_DIFFUSE, vector); GL_POSITION, GL_AMBIANT, GL_DIFFUSE, GL_SPECULAR. glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 2.0); glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 1.0); glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.5); /* Vecteurs normaux */ glNormal3f, glNormal3fv /* Modle dclairement et lumire ambiante */ glShadeModel(GL_FLAT); glShadeModel(GL_SMOOTH); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, vector);

A.10

Vertex Arrays

void glEnableClientState(GLenum array); GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_NORMAL_ARRAY, GL_TEXTURE_COORD_ARRAY void glDisableClientState(GLenum array); void glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); void glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); void glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer); void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); void glDrawElements(GLenum mode, GLsizei count, GLenum type, 67

Rmy Malgouyres, Universit Clermont 1

http ://laic.u-clermont1.fr/ mr/

OpenGL

void *indices); GL_POINTS, GL_LINES, GL_LINE_STRIP , GL_LINE_LOOP, GL_POLYGON, GL_QUADS, GL_QUAD_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN. void glArrayElement(GLint numVertex);

A.11

Temps

glutGet(int); GLUT_ELAPSED_TIME

68