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

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

Plus en détail

Interfaces de programmation 3D Objectifs du cours Interface de

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

Plus en détail