OpenGL (Mesa)
Transcription
OpenGL (Mesa)
OpenGL (Mesa) La bibliothèque standard 2D/3D Christian N GUYEN Département d’informatique Université de Toulon et du Var OpenGL (Mesa) – p.1/88 Introduction OpenGL est devenu un standard graphique de fait car il possède des capacités graphiques avancées associées à un modèle de programmation simple. Sa portabilité est assurée par le fait qu’il ne propose pas de pilote graphique propre à chaque plate forme. Il se présente comme une bibliothèque orientée uniquement vers la manipulation d’objets 3D et incorporable dans n’importe quel sous système fenêtré (X Window, Windows NT) ou non. Ses spécifications sont adaptées aux architectures graphiques actuelles OpenGL (Mesa) – p.2/88 Historique GKS : Graphics Kernel System, bibliothèque 2D, PHIGS et PHIGS+ Programmer’s Hierarchical Interactive Graphics System : basé sur GKS, standard ANSI. Encapsulation de la description et des attributs d’objets 3D dans une liste d’affichage (display list. Inconvénients : modification de la structure très lourde, pas d’intégration des techniques "avancées" de rendu, PEX (PHIGS Extension to X), ajoute le rendu immédiat mais comporte les mêmes défauts que PHIGS+ en y ajoutant différentes versions pas totalement compatibles. OpenGL, créé au début des années 90 par Silicon Graphics. OpenGL (Mesa) – p.3/88 Fonctionnalités OpenGL propose des techniques de rendu avancé, aussi bien en mode immédiat qu’au travers de listes d’affichage (display list). Il se présente de la même façon que les autres bibliothèques graphiques, comme une interface logicielle d’une architecture graphique : plusieurs centaines de procédures et fonctions de spécification et de manipulation d’objets 2D/3D avec leurs attributs. L’affichage comprend aussi bien X Window que d’autres interfaces graphiques (telles que Windows NT). OpenGL (Mesa) – p.4/88 Fonctionnalités OpenGL permet de construire des primitives dans la mémoire image (frame buffer), dans un certain mode. Toutes opérations (primitives, modes, ...) se fait par l’intermédiaire de commandes (sous la forme d’appels de procédures ou de fonctions). Le modèle d’interprétation des commandes OpenGL est le modèle client-serveur. Les primitives géométriques (points, segments, polygones) sont définies par l’intermédiaire de sommets. Un ensemble de données est associé à chaque sommet : position, normale, couleur et texture. Chaque sommet est calculé indépendamment. OpenGL (Mesa) – p.5/88 Fonctionnalités OpenGL fournit un contrôle direct sur les opérations 2D/3D fondamentales : matrices de transformation, coefficients des équations de la lumière, méthodes d’antialiasing, opérations de mise à jour des pixels Par contre, il n’existe aucune fonction permettant de modéliser les objets complexes : l’ensemble des outils permet de décrire l’apparence de l’objet et non l’objet lui-même. OpenGL (Mesa) – p.6/88 Portabilité Les effets des commandes sont contrôlés en bout de chaîne par le système de gestion de fenêtres : détermine les portions de la mémoire image accessible à OpenGL, communique la structure de cette portion à OpenGL, génère l’image sur l’écran à partir de la mémoire image (incluant des transformations propres à la mémoire image telle que la correction gamma). L’initialisation du système graphique est conditionnée par celle du gestionnaire de fenêtre. Les entrées utilisateurs sont aussi à la charge du gestionnaire de fenêtres. OpenGL (Mesa) – p.7/88 Bibliothèques Plusieurs bibliothèques sont développées à partir d’OpenGL afin d’apporter des fonctionnalités non-disponibles dans la bibliothèque OpenGL elle-même : GLU (OpenGL Utility Library) : décomposition de polygones concaves, description et affichage des courbes et des surfaces NURBS, définition de surfaces quadriques. GLUT (OpenGL Utility Toolkit) : jeu de routines pour la gestion des fenêtres OpenGL et les interactions avec le système d’exploitation indépendamment de celui-ci et du gestionnaire de fenêtres. GLUI (OpenGL User Interface Library) : bibliothèque en C++ qui permet de compléter la bibliothèque de gestion de fenêtres OpenGL, GLUT (boutons, les cases à cocher, . . .). OpenGL (Mesa) – p.8/88 Implémentations Plusieurs implémentations d’OpenGL (exploitant l’accélération 3D fournie par le matériel) existent pour Windows, de nombreuses stations Unix et Mac OS. Il existe une implémentation libre de cette bibliothèque, nommée Mesa, créée en 1993 par Brian Paul et qui utilise la même API, ce qui permet : de se passer de la licence OpenGL dans la plupart des cas de faire tourner des applications OpenGL sur des terminaux X qui y sont en principe inaptes OpenGL (Mesa) – p.9/88 Intérêt d’OpenGL pour SGI SGI met à chaque fois dans le domaine public la version N-1 de GL, bibliothèque graphique de GL. Cette approche marketing décourage la concurrence (OpenGL étant gratuit et ouvert, pourquoi développer autre chose ?) dissuade la modification d’OpenGL (car tout ajout serait à recommencer dans la version d’OpenGL suivante) donne aux stations SGI un avantage concurrentiel substantiel, puisque GL a toujours une longueur d’avance sur OpenGL. OpenGL (Mesa) – p.10/88 Utilisations Certains logiciels utilisent OpenGL pour gérer l’ensemble de leur interface, même 2D, comme Blender, ou la version SGI de X11. Liste non-exhaustive de jeux vidéos utilisant OpenGL : Doom 3 Half-Life Medal of Honor Neverwinter Nights Quake Star Wars : Knights of the Old Republic, Star Wars Jedi Knight : Jedi Academy, Star Wars Jedi Knight II : Jedi Outcast Unreal Tournament Warcraft 3, World of Warcraft Wolfenstein : Enemy Territory OpenGL (Mesa) – p.11/88 Le pipeline graphique d’OpenGL Per−Vertex Operations Sommets Evaluator Primitive Assembly Display Rasterization List Pixels Pixel Operations Per−Fragment Operations Frame Buffer Texture Memory Des opérations élémentaires OpenGL (Mesa) – p.12/88 Sommets et primitives OpenGL (Mesa) – p.13/88 Sommets et primitives Objets Sommets générés point chaque sommet donne la position d’un point line strip liste de segments jointifs line loop comme line strip mais le 1er et le dernier sommet forment un segment separate line chaque paire de sommets décrit un segment polygon les sommets décrivent un polygone convexe triangle strip chaque sommet suivant le 2ième décrit un triangle triangle fan chaque sommet suivant le 2ième décrit un triangle avec le précédent et le 1er point separate triangle chaque triplet de sommets décrit un triangle quadrilateral strip chaque paire de sommets décrit un quadrilatère avec la paire précédente independent quad chaque quadruplet de sommets décrit un quadrilatère OpenGL (Mesa) – p.14/88 Sommets et primitives 4 5 2 1 1 0 2 3 3 4 0 1 3 triangle strip 4 triangle fan 0 2 quadrilateral strip Exemple : glBegin(GL_POLYGON) glVertex3i(0, 0, 0); glVertex3i(0, 1, 0); glVertex3i(1, 0, 1); glEnd(); OpenGL (Mesa) – p.15/88 Sommets et primitives coord. transformée 1 sommet du sommet transformation sommet/normale normale courante luminosité couleur finale fonction de génération matrice de coord. finale des coord. de texture texture de la texture couleur courante texture courante position orientation matrice identité Association des valeurs courantes et d’un sommet OpenGL (Mesa) – p.16/88 Les polygones Définition : alternance de glNormal* et de glVertex* dans un glBegin/glEnd. Chaque normale doit être orientée vers l’extérieur de la surface. Remarque : glEnable(GL_NORMALIZE); Orientation des faces (counter clockwise ou CCW) : glFrontFace(mode) avec mode = (CCW, CW). OpenGL (Mesa) – p.17/88 Les polygones Les polygones ont deux faces glPolygonMode(face, mode) avec face = (FRONT, BACK, FRONT_AND_BACK) et mode = (POINT, LINE, FILL), Elimination des faces arrières par glCullFace(mode) avec mode = (FRONT, BACK, FRONT_AND_BACK). Subdivision explicite d’un polygone en polygones convexes par élimination des arêtes indésirables : glEdgeFlag(GL_FALSE);. OpenGL (Mesa) – p.18/88 Couleurs et affichage OpenGL (Mesa) – p.19/88 La couleur Définition (non modifiable) : quadruplets (R, V, B, A) ou table des couleurs. Exemple : glColor3f(1.0, 0.0, 0.0); LUT : portage, peu de plans, colormap animation, . . . RVBA : texture, lumière, ombrage, flou, antialiasing, mélange (blending), . . . Nombre de bits alloué à chaque composante couleur : glGetIntegerv(compcoul) avec compcoul = (GL_RED_BITS, ..., GL_INDEX_BITS). Tramage (dithering) : glEnable(GL_DITHER); (cf. double-buffer). OpenGL (Mesa) – p.20/88 Affichage OpenGL travaille par défaut en mode immédiat. L’initialisation se fait par glClear* : glClearColor(0, 0, 0, 0); // couleur de fond glClearDepth(0); // profondeur par defaut glClear(GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT); ATTENTION : réinitaliser le Z-buffer entre chaque changement de vue par : glClear(GL_DEPTH_BUFFER_BIT); Forcer la fin d’un dessin : glFlush(); (modèle client-serveur). OpenGL (Mesa) – p.21/88 Décrire une scène #include #include #include #include <math.h> <stdio.h> <stdlib.h> "glut.h" GLfloat light_diffuse[] = { 1.0, 0.0, 0.0, 1.0 }; GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; GLUquadricObj* obj; void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glCallList(1); /* rendu de la display_list sphere */ glutSwapBuffers(); } void init(void) { obj = gluNewQuadric(); gluQuadricDrawStyle(obj, GLU_FILL); glNewList(1, GL_COMPILE); gluSphere(obj, 1.0, 20, 20); glEndList(); OpenGL (Mesa) – p.22/88 Décrire une scène glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_POSITION, light_position); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST); glMatrixMode(GL_PROJECTION); gluPerspective(40.0, 1.0, 1.0, 10.0); glMatrixMode(GL_MODELVIEW); gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glTranslatef(0.0, 0.0, -1.0); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutCreateWindow("Sphere"); glutDisplayFunc(display); init(); glutMainLoop(); } OpenGL (Mesa) – p.23/88 Copie d’écran OpenGL (Mesa) – p.24/88 Visualisation OpenGL (Mesa) – p.25/88 Visualisation OpenGL (Mesa) – p.26/88 Visualisation 1. positionner, orienter la caméra et agencer la scène : une seule transformation (glMatrixMode(GL_MODELVIEW);), 2. choix de l’objectif (glMatrix-Mode(GL_PROJECTION);), 3. développement, choix de la taille de l’image papier (viewport transformation). glLoadIdentity(); glTranslate(); glRotate(); glOrtho(); glScale(); glFrustum(); vertex/normal modelview projection perspective viewport window coord. matrix matrix division transformation coord. glViewport(); (x, y, z, w) coord. divisées par w coord. dans le coord. repère de l’oeil clippées NDC OpenGL (Mesa) – p.27/88 Fonctions prédéfinies gluLookAt(point, refpoint, upvector) : positionner intuitivement la caméra. Définition du volume perspective : glFrustum() ou plus intuitif gluPerspective(T, aspect, near, far) avec T : profondeur de champ. T [0, 180] aspect = w/h w h near far La pyramide de vision perspective OpenGL (Mesa) – p.28/88 Décrire une scène (2) #include <GL/glut.h> #include <stdlib.h> void init(void) { glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel (GL_FLAT); } void display(void) { glClear (GL_COLOR_BUFFER_BIT); glColor3f (1.0, 1.0, 1.0); glLoadIdentity (); /* clear the matrix */ /* viewing transformation */ gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glScalef (1.0, 2.0, 1.0); /* modeling transformation */ glutWireCube (1.0); glFlush (); } void reshape (int w, int h) { glViewport (0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode (GL_PROJECTION); glLoadIdentity (); glFrustum (-1.0, 1.0, -1.0, 1.0, 1.5, 20.0); glMatrixMode (GL_MODELVIEW); } OpenGL (Mesa) – p.29/88 Copie d’écran (2) OpenGL (Mesa) – p.30/88 Composition de transformations void display(void) { glClear (GL_COLOR_BUFFER_BIT); glColor3f (1.0, 1.0, 1.0); glPushMatrix(); glutWireSphere(1.0, 20, 16); /* draw sun */ glRotatef ((GLfloat) year, 0.0, 1.0, 0.0); glTranslatef (2.0, 0.0, 0.0); glRotatef ((GLfloat) day, 0.0, 1.0, 0.0); glutWireSphere(0.2, 10, 8); /* draw planet */ glPopMatrix(); glutSwapBuffers(); } OpenGL (Mesa) – p.31/88 Les piles de matrices Chaque type de matrice possède sa propre pile de matrices (projection : 2 ; modelview : 32). Notion pratique pour construire des modèles hiérarchiques (transformation relative ; indépendantes : glLoadIdentity). Exemple, une voiture, 4 roues et 5 boulons par roue : 1. dessin de la voiture 2. mémorisation de son origine 3. translation relative appropriée pour placer la première roue 4. mémorisation de la position courante 5. 5 translations puis rotations pour les 5 boulons 6. suppression de la translation pour revenir à l’origine de la voiture 7. translation relative appropriée pour placer la deuxième roue ... OpenGL (Mesa) – p.32/88 Les piles de matrices Le mécanisme de pile permet la mémorisation de la position courante (glPushMatrix) et le retour à la position précédente (glPopMatrix). Exemple : void Roue_Boulons() { Roue(); for (int i = 0 ; i < 5 ; i++) { glPushMatrix(); glRotatef(degre*i, 0, 0, 1); // autour de Z glTranslatef(Xb, 0, 0); Boulon(); // ATTENTION : R*T*Boulon() glPopMatrix(); } } void Quatre_Roues() { glPushMatrix(); glTranslatef(Xr1, 0, Zr1); Roue_Boulons(); glPopMatrix(); glPushMatrix(); glTranslatef(Xr1, 0, Zr2); Roue_Boulons(); glPopMatrix(); ... } OpenGL (Mesa) – p.33/88 Les listes d’affichage OpenGL (Mesa) – p.34/88 Exemple : affichage d’un cercle solution 1 : glBegin(GL_POLYGON) for (i=0 ; i<100 ; i++) { // COUTEUX ! mycos = cos(i*2*Pi/100); // COUTEUX ! mysin = sin(i*2*Pi/100); glVertex2f(mycos, mysin); } glEnd(); solution 2 : avec un tableau glBegin(GL_POLYGON) for (i=0 ; i<100 ; i++) // COUTEUX ! glVertex2fv(&coord[i][0]); glEnd(); LA solution : construire le cercle une fois et mémoriser la construction pour un usage répété. OpenGL (Mesa) – p.35/88 Display lists Exemple : glNewList(MY_CIRCLE, GL_COMPILE); // ou GL_COMPILE_AND_EXECUTE glBegin(GL_POLYGON) ... glEnd(); glEndList(); ... glCallList(MY_CIRCLE); La notion de hiérarchie est également présente : glNewList(...); glCallList(...); glTranslatef(...); glCallList(...); glEndList(); OpenGL (Mesa) – p.36/88 Autres possibilités Vecteurs de listes d’affichage : int glGenLists(range) alloue range identificateurs contigües, glDeleteLists(range) libère un intervale d’indices, int glIsList(list) vrai si list est déjà utilisé. OpenGL (Mesa) – p.37/88 Autres possibilités : glCallLists prend comme arguments un tableau d’entiers (offsets) ; utiliser lorsque les indices ont une signification particulière : Execution de plusieurs listes d’affichage alphabet = glGenLists(128); glNewList(alphabet+’A’, GL_COMPILE); drawletter(Adata); glEndList(); ... glListBase(alphabet); lg = strlen(mot); // mot = "ABC" glCallLists(lg, GL_BYTE, mot); OpenGL (Mesa) – p.38/88 Mémorisation d’attributs de segments GLuint offset; offset = glGenLists(3); glNewList(offset, GL_COMPILE); glDisable(GL_LINE_STIPPLE); glEndList(); glNewList(offset+1, GL_COMPILE); glEnable(GL_LINE_STIPPLE); glLineStipple(1, 0x0F0F); glEndList(); glNewList(offset+2, GL_COMPILE); glEnable(GL_LINE_STIPPLE); glLineStipple(1, 0x1111); glEndList(); #define drawOneLine(x1, y1, x2, y2) glBegin(GL_LINES); \ glVertex2f((x1), (y1)); glVertex2f((x2), (y2)); glEnd(); glCallList(offset); drawOneLine(50.0, 125.0, 350.0, 125.0); glCallList(offset+1); drawOneLine(50.0, 100.0, 350.0, 100.0); glCallList(offset+2); drawOneLine(50.0, 75.0, 350.0, 75.0); OpenGL (Mesa) – p.39/88 Copie d’écran OpenGL (Mesa) – p.40/88 Le réalisme OpenGL (Mesa) – p.41/88 Ombre et lumière Shading : glShadeModel(mode) avec mode = (GL_FLAT, GL_SMOOTH). La lumière : codage RVB pour les lumières et la matière : lumière : correspondent au pourcentage d’intensité de chaque couleur, matière : proportion réfléchie de chaque composante couleur. Soit (lr , lv , lb ) les composantes de la lumière émise et (mr , mv , mb ) celles de la matière, la lumière parvenant à l’oeil est donnée par (lr ∗ mr , lv ∗ mv , lb ∗ mb ). OpenGL (Mesa) – p.42/88 Rendu d’une sphère Nécessite les étapes suivantes : 1. définition des vecteurs normaux de chaque sommet des objets, 2. création, sélection et position d’une ou de plusieurs sources lumineuses, 3. création et sélection d’un modèle de lumière, qui définit le niveau de la contribution ambiante et la position effective du point de vue (local ou à l’infini), 4. définition des propriétés de la matière pour les objets de la scène. OpenGL (Mesa) – p.43/88 Et la lumière fut void init(void) { GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat mat_shininess[] = { 50.0 }; GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel (GL_SMOOTH); 4 3 2 glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); glLightfv(GL_LIGHT0, GL_POSITION, light_position); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST); } void display(void) { glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 1 glutSolidSphere (1.0, 20, 16); glFlush (); } OpenGL (Mesa) – p.44/88 Copie d’écran OpenGL (Mesa) – p.45/88 Création des sources lumineuses Paramètre Valeur par défaut GL_AMBIENT GL_DIFFUSE GL_SPECULAR GL_POSITION GL_SPOT_DIRECTION GL_SPOT_EXPONENT GL_SPOT_CUTOFF GL_CONSTANT_ATTENUATION GL_LINEAR_ATTENUATION GL_QUADRATIC_ATTENUATION (0.0, 0.0, 0.0, 1.0) (0.0, 0.0, 0.0, 1.0) (0.0, 0.0, 0.0, 1.0) (0.0, 0.0, 1.0, 0.0) (0.0, 0.0, -1.0) 0.0 180.0 1.0 0.0 0.0 Source lumineuse directionnelle (+Z) sans attenuation. OpenGL (Mesa) – p.46/88 Création des sources lumineuses Activation : glEnable(GL_LIGHTi ) avec i = 0..7. Prise en compte des calculs associés aux sources lumineuses : glEnable(GL_LIGHTING); La lumière GL_LIGHT0 est définie pas défaut par les paramètres suivants : GL_AMBIENT(0,0,0,1), GL_DIFFUSE(1,1,1,1), GL_SPECULAR(1,1,1,1), GL_POSITION(0,0,1,0). OpenGL (Mesa) – p.47/88 Mouvement d’une lumière void display(GLint angle) { GLfloat light_position[] = { 0.0, 0.0, 1.5, 1.0 }; glClear(GL_COLOR_BUFFER_BIT) | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glTranslatef(0.0, 0.0, -5.0); glPushMatrix(); glRotated((GLdouble) angle, 1.0, 0.0, 0.0); glLightfv(GL_LIGHT0, GL_POSITION, light_position); glPopMatrix(); auxSolidTorus(); glPopMatrix(); glFlush(); } OpenGL (Mesa) – p.48/88 Les sources lumineuses (suite) Paramètres : de couleurs : GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, atténuation (avec position) : 1/(kc + kl .d + kq .d2 ) GL_CONSTANT_ATTENUATION (kc ), GL_LINEAR_ATTENUATION (kl ), GL_QUADRATIC_ATTENUATION (kq ), OpenGL (Mesa) – p.49/88 Les spots GL_SPOT_DIRECTION, GL_SPOT_EXPONENT (focalisation) : l’intensité lumineuse diminue du centre à la périphérie comme le cosinus de l’angle entre l’axe et l’objet éclairé à la puissance GL_SPOT_EXPONENT, GL_SPOT_CUTOFF (angle d’ouverture) : de 0 à 90˚, entre l’axe et une génératrice du cône. OpenGL (Mesa) – p.50/88 Modèle d’illumination Contribution ambiante glLightModel*(GL_LIGHT_MODEL_AMBIENT, ...) Local ou à l’infini (par défaut) : glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE) Plan de coupe et prise en compte des faces arrières : glLightModeli(LIGHT_MODEL_TWO_SIDE, GL_TRUE) OpenGL (Mesa) – p.51/88 Propriétés de la matière glMaterial*(face, type, param) : Type Valeur par défaut GL_AMBIENT GL_DIFFUSE GL_AMBIENT_AND_DIFFUSE GL_SPECULAR GL_SHININESS GL_EMISSION GL_COLOR_INDEXES GL_COLOR_INDEXES (0.2, 0.2, 0.2, 1.0) (0.8, 0.8, 0.8, 1.0) (0.0, 0.0, 0.0, 1.0) 0.0 (0.0, 0.0, 0.0, 1.0) (0, 1, 1) (0, 1, 1) Diminution du coût en prenant en compte la couleur courante (précédé de glColor*) : glColorMaterial(face, mode), rendu actif par glEnable(GL_COLOR_MATERIAL). OpenGL (Mesa) – p.52/88 Mélange, antialiasing et flou OpenGL (Mesa) – p.53/88 Mélange (blending) glEnable(GL_BLEND); calcul de la couleur finale : (Rs .Sr + Rd .Dr , Vs .Sv + Vd .Dv , Bs .Sb + Bd .Db , As .Sa + Ad .Da ), le calcul des facteurs est défini par la fonction glBlendFunc(Fs , Fd ), exemple en 2D : // 25% opaque, 75% transparent glBlendFunc(GL_ONE, GL_ZERO); // 1xRs, 1xVs, 1xBs, 1xAs // dessin du 1er objet ... // 2ieme objet avec alpha = 0,25 : 0,25xRs + 0,75xRd, ... glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); la couleur résultant dépend de l’ordre dans lequel on affiche les primitives graphiques (glDepthMask(GL_FALSE)). OpenGL (Mesa) – p.54/88 Antialiasing Multiplication de la valeur alpha du fragment par sa couverture (glEnable(GL_BLEND)) i.e la fraction en pourcentage de la surface du pixel recouvert par le fragment. OpenGL (Mesa) – p.55/88 Antialiasing Détermination de la qualité du rendu : glHint(cible, hint) avec : cible = GL_POINT_SMOOTH_HINT, GL_LINE_SMOOTH_HINT, GL_POLYGON_SMOOTH_HINT, GL_FOG_HINT (brouillard par pixel ou par sommet), GL_PERSPECTIVE_CORRECTION_HINT (interpolation des couleurs et des textures), hint = (GL_FASTEST option la plus efficace, GL_NICEST option grande qualité de rendu, GL_DONT_CARE aucune préférence). OpenGL (Mesa) – p.56/88 Antialiasing des points et des droites glEnable(GL_POINT_SMOOTH) glEnable(GL_LINE_SMOOTH), glEnable(GL_BLEND) ou et glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) A noter qu’effectuant des mélanges, on doit prendre en compte l’ordre du rendu. OpenGL (Mesa) – p.57/88 Antialiasing des polygones 1. glEnable(GL_POLYGON_SMOOTH) : les pixels sur les arêtes des polygones ont une valeur α fonction de leur couverture, glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST), 2. glDisable(GL_DEPTH_TEST) : pour que les fragments soient tous pris en compte, glEnable(GL_BLEND), glBlendFunc(GL_SRC_ALPHA_SATURATE, GL_ONE), (GL_SRC_ALPHA_SATURATE = à chaque composant facteurs (f, f, f, 1) avec f = min(αs , 1 − αd ), i.e un pixel avec un α grand sera peu affecté par les fragments suivants), 3. glCullFace(GL_BACK), glEnable(GL_CULL_FACE), glClearColor(0.0, 0.0, 0.0, 0.0). OpenGL (Mesa) – p.58/88 Antialiasing : exemple OpenGL (Mesa) – p.59/88 Antialiasing : exemple void display(void) { GLfloat mat_solid[] = { 0.75, 0.75, 0.0, 1.0 }; GLfloat mat_zero[] = { 0.0, 0.0, 0.0, 1.0 }; GLfloat mat_transparent[] = { 0.0, 0.8, 0.8, 0.6 }; GLfloat mat_emission[] = { 0.0, 0.3, 0.3, 0.6 }; glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix (); glTranslatef (-0.15, -0.15, solidZ); glMaterialfv(GL_FRONT, GL_EMISSION, mat_zero); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_solid); glCallList (sphereList); glPopMatrix (); OpenGL (Mesa) – p.60/88 Antialiasing : exemple glPushMatrix (); glTranslatef (0.15, 0.15, transparentZ); glRotatef (15.0, 1.0, 1.0, 0.0); glRotatef (30.0, 0.0, 1.0, 0.0); glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_transparent); glEnable (GL_BLEND); glDepthMask (GL_FALSE); glBlendFunc (GL_SRC_ALPHA, GL_ONE); glCallList (cubeList); glDepthMask (GL_TRUE); glDisable (GL_BLEND); glPopMatrix (); glutSwapBuffers(); OpenGL (Mesa) – p.61/88 Flou de distance (fog) Fonction appliquée à chaque fragment : mélange de la couleur courante et d’une couleur constante (de flou) suivant un facteur de poids (distance). 1. glEnable(GL_FOG); 2. glFog*(nom, param) : mélange de la couleur du brouillard (GL_FOG_COLOR) avec celle du fragment courant suivant un facteur f (GL_FOG_MODE) : GL_EXP : f = e−(densite∗z) , 2 GL_EXP2 : f = e−(densite∗z) , GL_LINEAR : f = (end − z)/(end − start). OpenGL (Mesa) – p.62/88 Flou de distance (fog) exemple d’initialisation : glFog*(GL_FOG_DENSITY, 0.35), glFog*(GL_FOG_START, 1.0), glFog*(GL_FOG_END, 5.0) Couleur finale = f.Ci + (1 − f ).Cf , avec Ci couleur du fragment au bout du pipeline et Cf couleur du brouillard. OpenGL (Mesa) – p.63/88 Manipulation d’images OpenGL (Mesa) – p.64/88 Principes Groupe de valeurs destinées à la mémoire image (frame buffer). Non affectées par les opérations géométriques qui participent au pipeline graphique au cours de la discrétisation. Position courante écran : glRasterPos. glGetFloatv(GL_CURRENT_RASTER_POSITION, . . .) retourne la position courante dans l’espace écran. OpenGL (Mesa) – p.65/88 Bitmaps Utilisation la plus courante : l’affichage de caractères. rectangle de pixel n’ayant que les valeurs 0 et 1. fonction d’affichage d’une bitmap : glBitmap(la, ha, x0, y0, xs, ys, bitmap[]). Remarque : xs, ys s’ajoutent à la “rasterpos” après affichage de la bitmap. OpenGL (Mesa) – p.66/88 Pixmaps lecture en mémoire image et stockage en mémoire conventionnelle : glReadPixels(x, y, la, ha, format, type, pixels[]) avec format = GL_COLOR_INDEX, GL_RGB, . . .et type = GL_BYTE, GL_UNSIGNED_SHORT, affichage d’une image couleur à l’écran : glDrawPixels(la, ha, format, type, pixels[]) copie d’une zone rectangulaire de mémoire image à mémoire image (=glReadPixels() + glDrawPixels()) : glCopyPixels(x, y, la, ha, type) : normalement chaque pixel d’une image est associé à un pixel de l’écran. glPixelZoom(Dx, Dy) OpenGL (Mesa) – p.67/88 Stockage et transformation Paramètres permettant le décodage des valeurs stockées : format de stockage, sélection d’un sous-ensemble de données : glPixelStore(mode, param) avec mode = GL_PACK_ (ou GL_UNPACK_) suivi de SWAP_BYTES, LSB_FIRST, ROW_LENGTH, SKIP_ROWS, SKIP_PIXELS, ALIGNMENT. 111111 000000 000000 111111 000000 111111 000000 111111 000000 111111 000000 111111 000000 SKIP_PIXELS 111111 000000 111111 000000 111111 SKIP_ROWS ROW_LENGTH contrôle de la conversion qui peut être appliquée aux valeurs obtenues : dilatées, ajustées (glPixelTransfer*()) et tracées par l’intermédiaire de tables (glPixelMap*()). OpenGL (Mesa) – p.68/88 Définition d’une texture : spécification de la texture, chaque texel comporte 1, 2, 3 ou 4 élément(s) (des quadruplets RVBA) : Etape 1 glTexImage2D(GL_TEXTURE_2D, 0, 3, la, ha, bordure, format, type, *pixels) avec 0 : nombre de résolutions (mimaps), 3 : composantes R, V, B, la et ha : 2m + 2∗bordure, format : GL_RGB (ou index de couleur, RVBA, . . .), type : GL_UNSIGNED_BYTE (ou INT, SHORT, FLOAT, . . .), fonction de filtrage, appliquée lors du placage sur la primitive : glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_WRAP_[ST], GL_[CLAMP, REPEAT]) ; glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_[MAG, MIN]_FILTER, GL_[NEAREST, LINEAR]) ; OpenGL (Mesa) – p.69/88 Définition d’une texture (suite) : définition de son influence sur chaque pixel : mode DECAL (le texel remplace le pixel), MODULATE (la couleur du fragment est transformée) ou BLEND (mélange simple) : glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_[DECAL, MODULATE, BLEND]), Etape 2 Etape 3 : autoriser le placage glEnable(GL_TEXTURE_1D) (2D de texture : le plus souvent), : construire une scène, en spécifiant les coordonnées géométriques de texture. Etape 4 OpenGL (Mesa) – p.70/88 Exemple Mur de largeur la et de hauteur ha = 2/3la : glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glTexCoord2f(1.0, 0.0); glTexCoord2f(1.0, 2/3); glTexCoord2f(0.0, 2/3); glEnd(); glVertex2f(); glVertex2f(); glVertex2f(); glVertex2f(); 11111 00000 00000 11111 00000 11111 00000 11111 00000 11111 texture "mur" OpenGL (Mesa) – p.71/88 Exemple complet ... #define checkImageWidth 64 #define checkImageHeight 64 GLubyte checkImage[checkImageWidth][checkImageHeight][3]; void makeCheckImage(void) { // Create checkerboard texture } void myinit(void) { glClearColor (0.0, 0.0, 0.0, 0.0); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); makeCheckImage(); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth, checkImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, &checkImage[0][0][0]); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glEnable(GL_TEXTURE_2D); glShadeModel(GL_FLAT); } OpenGL (Mesa) – p.72/88 Exemple complet void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex3f(-2.0, -1.0, 0.0); glTexCoord2f(0.0, 1.0); glVertex3f(-2.0, 1.0, 0.0); glTexCoord2f(1.0, 1.0); glVertex3f(0.0, 1.0, 0.0); glTexCoord2f(1.0, 0.0); glVertex3f(0.0, -1.0, 0.0); glTexCoord2f(0.0, 0.0); glTexCoord2f(0.0, 1.0); glTexCoord2f(1.0, 1.0); glTexCoord2f(1.0, 0.0); glEnd(); glutSwapBuffers(); glVertex3f(1.0, -1.0, 0.0); glVertex3f(1.0, 1.0, 0.0); glVertex3f(2.41421, 1.0, -1.41421); glVertex3f(2.41421, -1.0, -1.41421); } OpenGL (Mesa) – p.73/88 Copie d’écran OpenGL (Mesa) – p.74/88 Le “pipeline graphique” (III) OpenGL (Mesa) – p.75/88 Evaluators Spécification de fonctions polynomiales à une inconnue (courbe de Bezier : C(u) = [X(u), Y (u), Z(u)]) ou deux inconnues (carreau de Bezier : S(u) = [X(u, v), Y (u, v), Z(u, v)]). Matrice de polynômes constituée dans la base de Bezier : glMap*(cible, u1, u2, pas, ordre, points[]) avec cible donnant le type des points de contrôle, u ∈ [u1 , u2 ], le pas de discrétisation et l’ordre du polynôme. OpenGL (Mesa) – p.76/88 Utilisation des evaluators En évaluant chaque terme de la matrice (glEvalCoord), en lui fournissant un point du domaine (en lieu et place de glVertex). void init(void) { ... glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]); glEnable(GL_MAP1_VERTEX_3); } void display(void) { ... glBegin(GL_LINE_STRIP); for (i = 0; i <= 30; i++) glEvalCoord1f((GLfloat) i/30.0); glEnd(); OpenGL (Mesa) – p.77/88 Utilisation des evaluators En définissant un sous-espace du domaine en utilisant la primitive glEvalMesh(mode, p1, p2) sur la définition du sous-espace par glMapGrid(pas, u1, u2) avec 0 ≤ p1 , p2 ≤ n. C’est tout à fait équivalent à : glBegin(GL_POINTS); for (i = p1 ; i <= p2 ; i++) glEvalCoord1(u1 + i*(u2-u1)/n); glEnd(); OpenGL (Mesa) – p.78/88 La mémoire image (frame buffer) La destination des fragments est la mémoire image, correspondant à un tableau m × n de pixels associé à la fenêtre allouée par OpenGL. Les plans sont regroupés dans différents buffers logiques (couleur, profondeur, “stencil” et accumulation) : buffer couleur (color buffer) et buffer de profondeur (depth buffer), buffer “stencil” (stencil buffer) : valeurs mises à jour lorsqu’un fragment atteint la mémoire image (algorithmes à plusieurs passes, restriction d’écriture à certaine zone de l’affichage, . . .), buffer d’accumulation (accumulation buffer) : données RVBA, accumulation d’une série d’images en une image finale composite (algorithmes multi-passes : anti-aliasing, effet de profondeur, flou de mouvement). Sélection d’un buffer image (double-buffer, stéréographie) : glDrawBuffer(mode) avec mode = (GL_FRONT, ...). OpenGL (Mesa) – p.79/88 Opérations per-fragment Un fragment est soumis à une série de tests et de modifications, avant d’être placé dans le buffer image, dans cet ordre : 1. test de découpe (scissor test), proche du test stencil mais portion rectangulaire uniquement, 2. test alpha (objets transparents ou textures partiellement transparentes (billboarding)) : (a) objets avec α = 1, (b) objets avec α 6= 1 et le test de profondeur inhibé. 3. test stencil, choix de la fonction de comparaison, de la valeur de référence, de la modification appliquée au fragment, 4. test de profondeur (depth test), 5. mélange (blending), 6. dithering, 7. opération logique, uniquement en mode “color index” (blittering) OpenGL (Mesa) – p.80/88 Entrée/sortie utilisateur Sélection et retour d’information (pour une impression sur un traceur par exemple). Dans ces deux modes, les informations d’affichage sont transmises à l’application plutôt qu’envoyer à la mémoire image. Conséquence : l’application est figée. A la sortie du mode sélection, OpenGL retourne une liste de primitives intersectées par le volume de visualisation (selection hit). La liste des primitives est retournée comme un tableau d’entiers (de “noms”) et des données associées (hit records). Une routine permet de déterminer quelle primitive est dessinée près du curseur de sélection (le picking est un cas particulier de sélection). OpenGL (Mesa) – p.81/88 Mécanisme de sélection choix du tableau utilisé pour retourner les sélections : glSelectBuffer(taille, buffer[]), mode sélection pour l’application : glRenderMode(GL_SELECT) (ou GL_RENDER ou GL_FEEDBACK), initialisation de la pile des noms par glInitNames() et glPushNames(), définition du volume de visualisation utilisé pour la sélection (a priori différent du volume de visualisation de rendu : utiliser glPushMatrix() et glPopMatrix() pour sauver le contexte), alternance de stockage des noms et de commandes de construction d’objets, sortie du mode sélection et traitement de la sélection retournée. OpenGL (Mesa) – p.82/88 Création de la pile des noms glInitNames(); // creation de la pile de noms glPushName(-1); // pour eviter les erreurs de pile ... glPushMatrix(); // sauve la modelview matrix glLoadName(1); // remplace le sommet de pile objet1(); glPushName(2); ... glPopMatrix(); OpenGL (Mesa) – p.83/88 L’enregistrement des “hits” En mode selection, une primitive qui intersecte le volume de visualisation génère un “hit”. Chaque enregistrement correspondant à un hit comprend 4 entrées : le nombre de noms dans la pile des noms, la valeur minimum (et maximum) en Z de l’ensemble des sommets des primitives intersectées par le volume de visualisation, le contenu de la pile des noms. OpenGL (Mesa) – p.84/88 Exemple : select.c OpenGL (Mesa) – p.85/88 Exemple : select.c /* processHits prints out the contents of the selection array */ void processHits (GLint hits, GLuint buffer[]) { GLint i; GLuint j, names, *ptr; printf ("hits = %d\n", hits); ptr = (GLuint *) buffer; for (i = 0; i < hits; i++) { /* for each hit */ names = *ptr; printf (" number of names for hit = %d\n", names); ptr++; printf(" z1 is %g;", (float) *ptr/0x7fffffff); ptr++; printf(" z2 is %g\n", (float) *ptr/0x7fffffff); ptr++; printf (" the name is "); for (j = 0; j < names; j++) { /* for each name */ printf ("%d ", *ptr); ptr++; } printf ("\n"); } } OpenGL (Mesa) – p.86/88 Exemple : select.c /* Note that the third and fourth triangles share one name */ #define BUFSIZE 512 void selectObjects(void) { GLuint selectBuf[BUFSIZE]; GLint hits; glSelectBuffer (BUFSIZE, selectBuf); (void) glRenderMode (GL_SELECT); glInitNames(); glPushName(0); glPushMatrix (); glMatrixMode (GL_PROJECTION); glLoadIdentity (); glOrtho (0.0, 5.0, 0.0, 5.0, 0.0, glMatrixMode (GL_MODELVIEW); glLoadIdentity (); glLoadName(1); drawTriangle (2.0, 2.0, 3.0, 2.0, glLoadName(2); drawTriangle (2.0, 7.0, 3.0, 7.0, glLoadName(3); drawTriangle (2.0, 2.0, 3.0, 2.0, drawTriangle (2.0, 2.0, 3.0, 2.0, 10.0); 2.5, 3.0, -5.0); 2.5, 8.0, -5.0); 2.5, 3.0, 0.0); 2.5, 3.0, -10.0); OpenGL (Mesa) – p.87/88 Exemple : select.c glPopMatrix (); glFlush (); hits = glRenderMode (GL_RENDER); processHits (hits, selectBuf); } Résultat : hits = 2 number of names z1 is 1; z2 is the name is 1 number of names z1 is 0; z2 is the name is 3 for hit = 1 1 for hit = 1 0 OpenGL (Mesa) – p.88/88
Documents pareils
Diapositive 1 - HAPCO
SGI met à chaque fois dans le domaine public la version N-1 de GL,
bibliothèque graphique de GL. Cette approche marketing
Interfaces de programmation 3D Objectifs du cours Interface de
Procédure d’affichage
Effacer l’écran
Description de la caméra
Placer et dessiner chaque objet