Vous êtes sur la page 1sur 8

Evasion

Membres

Publications

Images


Menu
OpenGL : les
lumires
Contenu
1. On dmarre
!!
"Que la lumire soit."
Moi ;-)
Nous allons maintenant discuter des sources de lumire. C'est un sujet assez
tendu et un peu plus compliqu que ce qu'on a vu prcdement. Et comme il y a
beaucoup dire, nous n'allons voir dans une premire partie que les gnralits et
les sources omnidirectionnelles (les 'omni ' pour les fans 3DS). Nous verrons les
spots dans le deuxime chapitre. Je vous prviens tout de suite : il y a beaucoup
plus de bla-bla que dans les autres, parce qu'il y a beaucoup expliquer, mme si
certains connaissent dj ces notions.
Comme d'habitude, reprenons notre programme de base avec la fonction Draw()
rduite au minimum :
void Draw()
{


glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
SwapBuffers(DC) // glutSwapBuffers(); pour glut
glutPostRedisplay(); // Uniquement pour GLUT
}

Le meilleur objet pour illustrer l'exemple des lumires est la sphre. Nous aurions
pu dessiner une sphre face par face comme pour le cube du tutorial sur les
couleurs, mais bon on n'est pas maso non plus. Alors on va utiliser une procdure
bien pratique de glut.h : glutSolidSphere(). Elle prend en arguments le rayon de
la sphre, le nombre de parallles, et le nombre de mridiens. Nous allons
illuminer cette sphre par une source de lumire ponctuelle situe au mme
endroit que nous. Mais pour que la sphre soit claire, il faut d'abord faire
quelques initialisations :
void InitGL()
{


glEnable(GL_DEPTH_TEST); // Active le test de profondeur

glEnable(GL_LIGHTING); // Active l'clairage

OpenGL : les lumires http://www-evasion.imag.fr/Membres/Antoine.Bouthors/teac...
1 sur 8 31/05/14 22:06

glEnable(GL_LIGHT0); // Allume la lumire n1
}

Le code parle de lui-mme : glEnable(GL_DEPTH_TEST) active le test de profondeur,
c'est--dire que si un point d'une face se situe derrire une autre face, il n'est pas
dessin. glEnable(GL_LIGHTING)active la gestion de lumires, et
glEnable(GL_LIGHT0)allume la lumire n1. Vous aurez bien sr compris qu'il suffit
de faire glEnable(GL_LIGHT1)pour allumer la lumire n2 etc. Vous disposez d'au
moins 8 sources de lumires, le nombre maximum (dfinit par la constant
GL_MAX_LIGHT) tant limit par votre systme. Maintenant que nous avons allum la
lumire, nous pouvons donc dessiner notre sphre :
void Draw()
{


glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glTranslated(0,0,-5);

glutSolidSphere(1,30,30);

SwapBuffers(DC) // glutSwapBuffers(); pour glut
glutPostRedisplay(); // Uniquement pour GLUT
}

2. Facteur de brillance et couleur
spculaire
!!
Et voil ce que a donne. Bon OK en 256 couleurs c'est
pas super mais on voit quand mme bien que c'est une
sphre, alors que sans lumire a aurait fait juste un
disque tout blanc et tout pas beau. Maintenant
plongons-nous encore plus dans les lumires : nous avons
vu dans le tutorial prcdent que chaque objet tait
constitu d'un matriau, avec des proprits comme la
couleurs ambiente, diffuse etc... Ces paramtres
dfinissent comment est rflchie la lumire sur les
sommets pour chaque composante (0 : composante totalement absorbe par
l'objet ; 1 : composante totalement rflchie par l'objet). Mais un matriau
dispose aussi d'une autre proprit : la brillance. Ce paramtre dfinit la taille de
la tache spculaire. Une valeur de 0 dfinit une tache spculaire la plus grande
possible, et une valeur de 128 dfinit une tache toute petite. La valeur par dfaut
est de 0, donc normalement la partie illumine devrait tre de la couleur
spculaire, sans dgrad. Or ici c'est bien la couleurs diffuse que l'on voit, et non
la spculaire. Pourquoi ? Et bien tout simplement parce que la couleur spculaire
par dfaut du matriau est nulle. Nous allons donc la changer. Pour cela, ce n'est
pas dur, nous l'avons vu dans le tutorial prcdent, il suffit d'appeler glColor()

OpenGL : les lumires http://www-evasion.imag.fr/Membres/Antoine.Bouthors/teac...
2 sur 8 31/05/14 22:06
en ayant pralablement choisi GL_SPECULAR avec glColorMaterial(). Mais il y a
un autre moyen de la modifier : c'est glMaterial(). En fait, glColor() est une
alternative glMaterial() pour modifier les couleurs d'un matriau. Si
GL_COLOR_MATERIAL est dsactiv (par dfaut), on utilise
glMaterial() pour changer les couleurs. S'il est activ,
alors on utilisera glColor(), et glMaterial() n'aura plus
d'effet sur les couleurs (par contre il en aura sur les autres
paramtres des matriaux). glMaterial() a l'avantage de
pouvoir tre appel entre glBegin() et glEnd() (glColor()
aussi, mais pas glColorMaterial() ), mais il est quand
mme plus lent que glColor(), c'est pourquoi il est
conseill d'utiliser glColor() plutt que glMaterial() pour
modifier les couleurs d'un matriau.
Bon, bref, si on met la couleur spculaire de notre sphre (1,1,1) comme elle le
devrait, on obtiendrait l'image que vous voyez droite. On
a plutt l'impression d'tre revenu au point de dpart :
l'objet est tout blanc, on ne distingue rien etc etc... Mais je
vous l'ai dit : c'est parce que l'indice de brillance
(shininess) est 0, ce qui fait que la tache spculaire est
tellement grande qu'elle a bouff la partie diffuse. Il suffit
donc de modifier ce paramtre grce glMaterial() pour
tout de suite avoir un aspect beaucoup plus raliste. Si on
rgle ce paramtre 100 (sa valeur peut tre comprise
entre 0 et 128), on obtient quelque chose dans le genre de ce que vous pouvez
voir votre gauche. C'est quand mme autrement plus joli. Mais pour ma part, je
ne suis pas entirement satisfait. En effet, la source de lumire est au mme
endroit que la camra, ce qui fait que toutes les partie visibles de l'objet sont
claires. Ceci serait plus beau si la source de lumire provenait d'un point dans
l'espace. Et c'est l que nous allons parler des lumires directionnelles
(directionnal lights) et ponctuelles (positionnal lights).
3. Lumire directionnelle et lumire
ponctuelle
!!
Ici encore les adeptes de 3DS ou autres POV n'auront aucun mal saisir ces
notions, puisque ce sont les bases de tout modeleur 3D qui se respecte. Allons-y
: une source de lumire ponctuelle est une source dont les rayons partent tous
du centre de la source. Une source de lumire directionnelle est une source dont
les rayons ont la mme direction en tout point de l'espace, comme une source
ponctuelle qui serait situe tellement loin de la scne que les rayons pourraient
tre considrs comme parallles. L'exemple parfait de lumire directionnelle
dans notre monde, qui est d'ailleurs cit dans n'importe quel bouquin expliquant
ce genre de trucs, est bien sr le soleil : tous ses rayons vont dans la mme
direction, que l'on soit Paris o Qubec, mme si des milliers de km sparent
ces 2 villes. Voil un petit shma histoire de vous claircir les ides, plutt que de
vous embrouiller avec mes explications douteuses :

OpenGL : les lumires http://www-evasion.imag.fr/Membres/Antoine.Bouthors/teac...
3 sur 8 31/05/14 22:06
4. Position de la source
!!
Voil, l je pense que vous comprenez ce que je veux dire. Nous allons donc
modifier notre source de lumire pour qu'elle rayonne de biais par rapport la
sphre. Mais au fait, quels sont les paramtres par dfaut de GL_LIGHT0 ? Et bien
elle est directionnelle et rayonne le long de l'axe z, dans le sens des valeur
ngatives. Donc si on se place par exemple en (5,5,5) en regardant le point (0,0,0)
avec gluLookAt(), on devrait voir une sphre claire de biais. Or, si vous faites le
test, vous verrez exatcement la mme image que lorsque vous tiez en (0,0,-5).
Pourquoi donc ? Et bien en fait la position des lumires est dtermine de la mme
faon que pour les primitives : avec la matrice modelview. Lorsque vous dfinissez
la postition de la lumire, elle est multiplie par la matrice modelview courante. Or
la position par dfaut de la lumire est dfinie l'initialisation et plus du tout
aprs. Donc s'il y a une modification de matrice aprs la dfinition de la position
de la lumire, cette dernire n'est pas affecte, tout comme une primitive.
Il faut donc redfinir la position de la lumire aprs les modifications de matrice,
comme pour tout objet, si vous voulez avoir une lumire stationnaire. Ca a l'air
bizarre et compliqu, mais en fait c'est plus pratique : vous pouvez effectuer des
transformations aux sources de lumire comme vous voulez comme si elles taient
des objets normaux, et en plus si vous voulez une source de lumire relative au
point de vue (comme par exemple une lampe de casque de mineur), il suffit de la
dfinir avant toute modification de matrice. Voil trois exemples-type pour illustrer
ces longues explications :
Lumire fixe, point de
vue mobile
Point de vue fixe,
lumire mobile
Point de vue mobile,
lumire relative au point
de vue
Vous aurez devin que le point jaune reprsente la lumire et les lignes rouges et

OpenGL : les lumires http://www-evasion.imag.fr/Membres/Antoine.Bouthors/teac...
4 sur 8 31/05/14 22:06
jaunes les axes X et Z. Voyons donc maintenant le code corespondant chacun
des exemples. Je ne rajoute pas les fonctions de dessin des lignes et du point,
histoire de ne conserver que l'essentiel.
4.1 Premier exemple : lumire fixe
!!
Il suffit d'effectuer en premier lieu les transformations, et ensuite de placer la
lumire et les objets :
double a=0;
int LightPos[4] = {0,0,3,1};
int MatSpec [4] = {1,1,1,1};

void Draw()
{
glMaterialiv(GL_FRONT_AND_BACK,GL_SPECULAR,MatSpec);
glMateriali(GL_FRONT_AND_BACK,GL_SHININESS,100);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,6,6,0,0,0,0,1,0);
glRotated(a,0,1,0);
glLightiv(GL_LIGHT0,GL_POSITION,LightPos);
glutSolidSphere(1,50,50);
a=+1;
SwapBuffers(DC) // glutSwapBuffers(); pour glut
glutPostRedisplay(); // Uniquement pour GLUT
}
On modifie d'abord les paramtres du matriau courant : couleur spculaire
blanche et braillance 100 (remarquez que comme le matriau est toujours le
mme, on aurait pu mettre ces lignes dans InitGL() ).
Vous voyez ensuite que l'on modifie les paramtres d'une source de lumire par
glLight{if}[v](). Il suffit de lui transmettre le nom de la lumire, le nom du
paramtre que l'on veut changer, et sa nouvelle valeur. Ici encore, le postfixe 'i'
signifie que l'on passe des entiers, 'f' que l'on passe des float, et 'v' que le
troisime paramtre est un pointeur sur les nouvelles valeurs.
Voyons maintenant de plus prs ce que l'on transmet comme position : il ne s'agit
pas comme on pourrait s'y attendre de trois valeurs x,y et z, mais de 4 valeurs.
Les trois premires sont effectivement les coordonnes cartsiennes, mais que
vient foutre ici le 4e lment ? Ben en fait c'est grce lui que vous allez
dterminer si une source est ponctuelle ou directionnelle (c'est vrai, quoi : je vous
bassine avec a depuis tout--l'heure, il fallait bien qu'il se trouve quelque part). Si
w (c'est son nom) est 0 comme dans l'exemple, alors la lumire est ponctuelle.
Sinon elle est directionnelle et son sens part du point position transmis vers le
point (0,0,0) (donc vitez de crer une lumire directionnelle avec comme position
le point (0,0,0) ). Essayez de changer la lumire de l'exemple en lumire
directionnelle, pour voir.

OpenGL : les lumires http://www-evasion.imag.fr/Membres/Antoine.Bouthors/teac...
5 sur 8 31/05/14 22:06
4.2 Deuxime exemple : lumire mobile
!!
L non plus c'est pas compliqu : il suffit de ne faire tourner que la lumire et non
la sphre, donc d'crire :
double a=0;
int LightPos[4] = {0,0,3,1};
int MatSpec [4] = {1,1,1,1};
void Draw()
{
glMaterialiv(GL_FRONT_AND_BACK,GL_SPECULAR,MatSpec);
glMateriali(GL_FRONT_AND_BACK,GL_SHININESS,100);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,6,6,0,0,0,0,1,0);
glRotated(a,0,1,0);
glLightiv(GL_LIGHT0,GL_POSITION,LightPos);
glRotated(-a,0,1,0);
glutSolidSphere(1,50,50);
a=+1;
SwapBuffers(DC) // glutSwapBuffers(); pour glut
glutPostRedisplay(); // Uniquement pour GLUT
}
Et voil. Au lieu de faire glLoadIdentity() puis gluLookAt() avant de dessiner la
sphre, j'ai mis glRotated(-a,0,1,0), cequi annule la rotation, donc revient au
mme. Si vous testez cet exemple, vous ne verrez en fait aucune diffrence par
rapport au prcdent, car vous n'avez pas de repre fixe. Le rsultat sera le mme
: on a l'impression que la lumire tourne autour de la sphre, car celle-ci est
tellement parfaite qu'on ne distingue pas si elle tourne ou non. Par contre, si vous
lui attribuez 5 mridiens et 5 parallles au lieu de 50, l vous verrez une
diffrence.

4.3 Troisime exemple : lumire relative au point de vue
!!
Comme je l'ai galement expliqu, il suffit de dfinir la position de la lumire avant
toute transformation pour que la position soit toujours la mme par rapport la
camra. Donc notre fonction Draw() sera comme ceci :
double a=0;
int LightPos[4] = {0,0,0,1};
int MatSpec [4] = {1,1,1,1};

void Draw()
{
glMaterialiv(GL_FRONT_AND_BACK,GL_SPECULAR,MatSpec);
glMateriali(GL_FRONT_AND_BACK,GL_SHININESS,100);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

OpenGL : les lumires http://www-evasion.imag.fr/Membres/Antoine.Bouthors/teac...
6 sur 8 31/05/14 22:06
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLightiv(GL_LIGHT0,GL_POSITION,LightPos);
gluLookAt(0,6,6,0,0,0,0,1,0);
glRotated(a,0,1,0);
glutSolidSphere(1,50,50);
a=+1;
SwapBuffers(DC) // glutSwapBuffers(); pour glut
glutPostRedisplay(); // Uniquement pour GLUT
}
Ici la lumire est ponctuelle et situe exactement au mme endroit que l'oeil
(remarquez que comme elle ne bouge jamais et ne se proccupe pas des
transformations, on aurait pu mettre glLightiv() dans InitGL() ). Si vous
conservez 50 mridiens et 50 parallles, vous aurez du mal voir la sphre
tourner. Ici encore, essayez 5 mridiens et 5 parallles, vous y verrez plus clair.
5. Attnuation
!!
Bon, vous en avez dj pas mal vu jusqu'ici, mais il reste encore quelques points
voir. Et notemment l'attnuation. En effet, il est rare de voir une lumire
ponctuelle pouvant clairer une distance infinie. Si vous tes capable de voir la
Grande Ourse de chez vous, je doute que votre lampe de chevet puisse clairer
aussi loin que cette toile. OpenGL vous permet d'ajouter des facteurs
d'attnuation vos sources de lumire. Comme une lumire directionnelle est
considre comme une lumire tant une distance infinie, l'attnuation n'est pas
valable pour ce genre de sources.
Vous disposez de 3 constantes d'attnuation pour chaque lumire :
GL_CONSTANT_ATTENUATION (appelons-la Kc), GL_LINEAR_ATTENUATION (Kl) et
GL_QUADRATIC_ATTENUATION (Kq). Si d est la distance d'un point la source de
lumire, la quantit de chaque composante de la lumire qui arrive ce point est
multiplie par : 1 / (Kc + Kl*d + Kq*d!). Pour changer les constantes
d'attnuation il suffit d'appeler glLight(). Par exemple,
glLightf(GL_LIGHT0,GL_QUADRATIC_ATTENUATION,.01f);
Mettra 0.01 la constante d'attnuation Kq de la lumire GL_LIGHT0.
Par dfaut, on a Kc=1, Kl=0 et Kq=0, donc la lumire n'est pas attnue. Si par
exemple vous choisissez pour Kc, Kl et Kq des valeurs respective de 0.1, 0 et 0.01,
vous pourrez obtenir quelque chose de ce genre :
Chaque sphre a un rayon de 0.4 et l'espace entre 2 centres est de 1. Notez qu'il
n'est pas possible d'attnuer une seuke composante (rouge, bleue ou verte) et que
toutes les couleurs de la lumire (ambiente, diffuse et spculaire) sont attnues.

6. Couleur
!!
OpenGL : les lumires http://www-evasion.imag.fr/Membres/Antoine.Bouthors/teac...
7 sur 8 31/05/14 22:06
Tiens, justement, qu'est-ce que c'est que a, "les couleurs de la lumire" ? On
connaissait dj les couleurs des matriaux, mais pas a. Et bien, comme vous
auriez pu vous en douter, chaque lumire a ses propres couleurs. En effet, un
girophare est rouge ou bleu, une lampe incandescence met une lumire plutt
jaune, le soleil couchant lance ses ultimes rayons rouge-orangs sur la verte
colline... Bref, y'a pas que les objets qui ont des couleurs : les lumires aussi ont
droit la diffrence. Et comme les objets, elles possdent chacune une couleur
ambiente, une diffuse et une spculaire. Prenons l'exemple d'un plafonnier dans
une pice : les rayons rebondissent sur les murs et les objet recoivent une lumire
dont la provenance est impossible dterminer tant la lumire a t disperse :
c'est la composante ambiente de la lumire. La lumire diffuse est ce qu'on
pourrait appeler la couleur relle de la source : c'est la couleur des rayons qui
viennent directement frapper l'objet. La couleur spculaire est la couleur de la
tache spculaire que produira la source. Pour un effet raliste, elle doit tre
identique la couleur diffuse.
Ces composantes ne suppriment bien sr pas les couleurs des matriaux : lors du
calcul de la couleur des sommets, les couleurs de la lumire et du matriau sont
mlanges. Par exemple, une lumire cyan (0,1,1) clairant une sphre jaune
(1,1,0) donnera une sphre verte (0,1,0). Pour modifier la couleur d'une source de
lumire, il faut bien sr appeler glLight(). Par exemple, pour mettre la lumire
diffuse de la lumire n1 (.5,.5,1), il suffit de faire
float LightDif[4] = {.5f,.5f,1.f,1.f};
glLightfv(GL_LIGHT0,GL_DIFFUSE,LightDif);
Pour ce qui est de la 4e composante, il s'agit de la composante alpha. Ne vous en
proccupez pas, elle ne sert rien pour l'instant (vous pouvez la mettre 0 si a
vous amuse, a ne changera rien).

Conclusion
!!
Et ben voil, je crois qu'on a fait le tour des sources ponctuelles (et directionnelles,
qui en sont des drives). On a tout de mme vu dans ce tutorial comment allumer
une lumire, changer sa couleur, sa position, ses facteurs d'attnuation, et si elle
est ponctuelle ou directionnelle. Entrainez-vous bien avec les exemples que je vous
ai donn (surtout au niveau de la position). On continuera la prochaine fois avec
les spots.
Antoche

! Les couleurs " Tutoriaux OpenGL " Les spots #

Last modified on Friday December 23rd, 2005 E-mail any comment
OpenGL : les lumires http://www-evasion.imag.fr/Membres/Antoine.Bouthors/teac...
8 sur 8 31/05/14 22:06