Modele de iluminare şi reflexie în OpenGL În lumea reală, atunci când lumina provenită de la diferite surse de lumină cade asupra obiectelor opace, o parte este absorbită de obiecte, iar o parte este reflectată. Ochiul percepe lumina reflectată de obiect, pentru a interpreta forma, culoarea şi alte detalii ale obiectului. Pentru calculul iluminării în grafica pe calculator trebuie să fie definite sursele de lumină şi interacńiunea dintre lumină şi suprafeńe. Un model de iluminare defineşte natura luminii emise de o sursă de lumină, adică distribuńia intensităńii luminii. Un model de reflexie descrie interacńiunea dintre lumină şi o suprafańă, în funcńie de proprietăńile suprafeńei şi natura sursei de lumină. Implementarea unui model de reflexie în procesul de calculare a intensităńii culorii fiecărui pixel este cunoscută sub numele de tehnică de umbrire. Biblioteca OpenGL implementează modelul de reflexie Phong şi modelele de umbrire poligonală şi umbrire Gouraud. În mod implicit, sistemul de iluminare este inactivat şi pentru desenarea primitivelor geometrice se foloseşte culoarea curentă. Pentru validarea iluminării obiectelor, se activează sistemul de iluminare OpenGL prin apelul funcńiei glenable(gl_lighting). Pentru calculul iluminării obiectelor trebuie să fie definite: sursele de lumină, materialul suprafeńelor, modelul de umbrire a suprafeńelor. 1. Specificarea culorii OpenGL permite utilizarea a două moduri de reprezentare a culorilor de afişare: - modul RGBA: pentru fiecare pixel se memorează valorile R (Red), G (Green), B (Blue) şi A (Alpha); - modul indexat: pentru fiecare pixel se memorează un număr, reprezentând un index într-o tabelă de culori. Modul RGBA este cel mai utilizat. În modul RGBA, pentru selectarea culorii curente se folosesc funcńiile glcolor#(). void glcolor3b s i f d ub us ui (TYPE r, TYPE g, TYPE b); void glcolor4b s i f d ub us ui (TYPE r, TYPE g, TYPE b, TYPE a); void glcolor3b s i f d ub us uiv (const TYPE *v); void glcolor4b s i f d ub us uiv (const TYPE *v); FuncŃiile glcolor3() specifică un triplet (R, G, B). FuncŃiile glcolor4() adaugă la tripletul (R, G, B) o valoare de opacitate, numită valoare alfa (A). Valorile R, G, B şi A variază în domeniul [ 0,1]. Valoarea implicită a opacităńii este 1.0. Când sunt specificate valori din afara domeniului [ 0,1], acestea se mapează liniar în acest interval. 1
2. Definirea surselor de lumină Lucrarea 8 În OpenGL se pot defini mai multe surse de lumină punctiforme. Numărul de surse de lumină admise variază în funcńie de implementare, dar cel puńin opt surse sunt disponibile în orice bibliotecă OpenGL. Fiecare sursă de lumină poate fi validată prin apelul funcńiei glenable(gl_lighti), unde i este indexul sursei de lumină. O sursă de lumină se caracterizează prin intensitate şi pozińia în scenă. Intensitatea unei surse de lumină se specifică pentru fiecare componentă de iluminare (ambientală, de difuzie şi speculară) printr-un vector în spańiul culorilor în modelul RGBA. PoziŃia unei surse se specifică printr-un vector în coordonate omogene corespunzătoare sistemului de referinńă universal. FuncŃia de definire a unui parametru al sursei de lumină este funcńia gllight#() care are mai multe variante în funcńie de tipul argumentelor. void gllightf(glenum light, GLenum pname, const GLfloat params); void gllighti(glenum light, GLenum pname, const GLint params); void gllightfv(glenum light, GLenum pname, const GLfloat *params); void gllightiv(glenum light, GLenum pname, const GLint *params); Argumentul light reprezintă indexul sursei de lumină şi poate lua un nume simbolic de forma GL_LIGHT0, GL_LIGHT1,..., GL_LIGHTi,unde 0 i GL_MAX_LIGHTS -1. Numărul maxim de surse de lumină depinde de implementarea bibliotecii. Argumentul pname specifică un parametru al sursei de lumină. Sunt acceptate mai multe valori, dinte care unele se referă la intensitatea culorii, iar altele la pozińia sursei (tabelul 1). pname Valoare implicită SemnificaŃie GL_AMBIENT (0.0, 0.0, 0.0, 1.0) intensitatea ambiantă a luminii (RGBA) GL_DIFFUSE (1.0, 1.0, 1.0, 1.0) intensitatea luminii difuze (RGBA) GL_SPECULAR (1.0, 1.0, 1.0, 1.0) intensitatea luminii speculare (RGBA) GL_POSITION (0.0, 0.0, 1.0, 0.0) pozińia (x, y,z, w) GL_SPOT_DIRECTION (0.0, 0.0, -1.0) direcńia (x, y, z) a spotului de lumină GL_SPOT_EXPONENT 0.0 exponentul spotului de lumină GL_SPOT_CUTOFF 180.0 unghiul spotului de lumină GL_CONSTANT_ATTENUATION 1.0 factor de atenuare constant GL_LINEAR_ATTENUATION 0.0 factor de atenuare liniar GL_QUADRATIC_ATTENUATION 0.0 factor de atenuare cuadratic Tabelul 1. Valorile GL_AMBIENT, GL_DIFFUSE şi GL_SPECULAR ale argumentului pname permit definirea componentelor intensităńii culorii sursei de lumină. În primele două funcńii argumentul params reprezintă valoarea care se va atribui parametrului indicat de pname. În celelalte două funcńii, argumentul params reprezintă un pointer la un vector de patru valori (de tip întreg sau virgulă flotantă), care specifică intensităńile RGBA ale componentei de iluminare ambientală, difuză şi speculară. Valorile implicite ale intensităńilor sunt (0.0, 0.0, 0.0, 1.0) pentru componenta ambientală şi pentru componenta difuză şi speculară a oricărei lumini cu excepńia luminii cu index 0, care are intensitatea difuză şi speculară implicită (1.0, 1.0, 1.0, 1.0). 2
În acest model de definire a sursei de lumină, componenta ambientală (GL_AMBIENT) se referă la intensitatea RGBA pe care o sursă de lumină o adaugă iluminării globale a scenei. Componenta de iluminare difuză (GL_DIFFUZE) este cel mai apropiat mod de reprezentare a ceea ce se consideră culoarea sursei de lumină. Componenta de iluminare (GL_SPECULAR) afectează culoarea zonei strălucitoare (hightlight) a obiectelor luminate de sursa respectivă. Valoarea transparenńei surselor de lumină (alpha) este ignorată dacă nu se validează calculul transparenńei (color blending). Valoarea GL_POSITION a argumentului pname permite definirea pozińiei sursei de lumină. În această situańie, argumentul params este un pointer la un vector de patru numere (întregi sau virgulă flotantă) care reprezintă pozińia în coordonate omogene în sistemul de referinńă universal al sursei de lumină. Această pozińie este transformată prin aplicarea valorii matricei de modelare-vizualizare din momentul apelului funcńiei gllight#(), astfel încât sursa de lumină va avea coordonatele transformate în sistemul de referinńă de observare, unde se calculează intensitatea în vârfurile primitivelor geometrice. Dacă componenta w a pozińiei este 0, atunci lumina este tratată ca o lumină direcńională plasată la infinit, în direcńia definită de componentele x, y, z şi se utilizează această direcńie pentru calculul componentelor de reflexie difuză şi speculară. Dacă w 0, atunci sursa este o sursă pozińională şi se foloseşte localizarea acesteia pentru calculul direcńiei de iluminare a suprafeńelor. PoziŃia implicită a unei surse este (0, 0, 1, 0), deci sursa este plasată la infinit pe axa z şi ea luminează obiectele în direcńia z. SecvenŃa de instrucńiuni pentru definirea intensităńii şi pozińiei sursei de lumină de indice 0 arată astfel: GLfloat light_ambient[] = 1.0, 0.0, 0.0, 0.0 ; GLfloat light_diffuse[] = 1.0, 0.0, 0.0, 0.0 ; GLfloat light_specular[] = 1.0, 1.0, 1.0, 0.0 ; GLfloat light_position[] = 1.0, 1.0, 1.0, 0.0 ; gllightfv(gl_light0, GL_AMBIENT, light_ambient); gllightfv(gl_light0, GL_DIFFUSE, light_diffuse); gllightfv(gl_light0, GL_SPECULAR, light_specular); gllightfv(gl_light0, GL_POSITION, light_position); În iluminarea reală, intensitatea luminii primite de un obiect scade odată cu creşterea distanńei acestuia fańă de sursa de lumină. Dat fiind că sursele de lumină direcńionale (care au w = 0 ) se consideră plasate la infinit, nu are sens calculul atenuării cu distanńa, astfel încât atenuarea este invalidată pentru astfel de surse. Pentru sursele pozińionale, se foloseşte un factor de atenuare cu valoarea: f 1 = (1) 2 k + k r k r c l + q unde: r = distanńa dintre sursa de lumină şi vârful în care se calculează iluminarea k = GL_CONSTANT_ATTENUATION; c k = GL_LINEAR_ATTENUATION; l k = GL_QUADRATIC_ ATTENUATION; q 3
Lucrarea 8 Implicit aceşti parametri au valorile k = 1, k = 0, k = 0, dar ei pot fi setańi prin apelul uneia din funcńiile gllightf() sau gllighti() astfel: c gllightf(gl_light0, GL_CONSTANT_ATTENUATION, 2.0); gllightf(gl_light0, GL_LINEAR_ ATTENUATION, 1.0); gllightf(gl_light0, GL_QUADRATIC_ ATTENUATION, 0.5); l Dacă se folosesc mai multe surse de lumină, pentru fiecare din ele se definesc componentele intensităńii, pozińia şi caracteristicile de atenuare. q 3. Definirea proprietăńilor materialelor În modele simple de reflexie (ca de exemplu cazul modelului Phong) se consideră că lumina reflectată de o suprafańă este constituită din trei componente: reflexia difuză; reflexia speculară; reflexia ambientală. Reflexia difuză joacă cel mai important rol în culoarea pe care o prezintă o suprafańă. Ea reprezintă culoarea pe care o are suprafańa luminată direct şi depinde de componenta de difuzie a luminii incidente, provenită de la una sau mai multe surse de lumină, de coeficientul de reflexie de difuzie (reflectanńa de difuzie) a materialului şi de unghiul dintre direcńia luminii şi normala la suprafańă. PoziŃia de observare nu influenńează componenta de difuzie a luminii reflectate. În cazul unei surse punctiforme intensitatea luminii difuzate este: I d = k d k c I r 0 r l n, (2) 2 + k r+ k r l q unde k d - coeficientul de reflexie de difuzie, l r - vectorul unitate îndreptat spre sursa de lumină, n r normala la suprafańă, r - distanńa la sursa respectivă, I0 - intensitatea sursei de lumină. Reflexia ambientală afectează culoarea de ansamblu pe care o prezintă o suprafańă şi ea devine sesizabilă atunci când suprafańa nu este luminată direct. Ca şi reflexia difuză, această componentă nu depinde de pozińia de observare. În modelul de reflexie Phong intensitatea dată de componenta ambientală este: I = k I, (3) g a a k a fiind coeficientul de reflexie pentru lumina ambientală. Reflexia speculară produce iluminarea mai puternică (hightlight) a unei zone a obiectului, în funcńie de pozińia de observare (fig.1). În cazul unei singure surse punctiforme, intensitatea luminii reflectate specular este: I Is ks 0 r = ( v r ) n 2, (4) k + k r+ k r c l q 4
unde k s - coeficient de reflexie speculară, r - versorul direcńiei de oglindire, v r - versorul direcńiei de observare şi n - coeficient care simulează rugozitatea materialului. l r n r r r Ω v r Fig. 1. Reflexia speculară Phong Prin combinarea relańiilor (2)-(4) se obńine relańia de calcul a culorii unei suprafeńe: c r r r [ k l n+ k ( v) ] n I 0 r 2 d s lr+ kqr I = Iaka +. (5) k + k Din cele prezentate anterior rezultă că pentru calculul intensităńii culorii unei suprafeńe, trebuie definińi coeficienńii de reflexie ambientală, difuză şi speculară. Aceste proprietăńi sunt considerate proprietăńi de material ale suprafeńei şi se specifică prin apelul uneia sau mai multora din cele patru variante ale funcńiei glmaterial#(): void glmateriali(glenum face, GLenum pname, GLint param); void glmaterialf(glenum face, GLenum pname, GLfloat param); void glmaterialiv(glenum face, GLenum pname, GLint *param); void glmaterialfv(glenum face, GLenum pname, GLfloat *param); În aceste funcńii, argumentul face este numele feńei şi depinde de orientarea acesteia; poate lua ca valori constantele simbolice GL_FRONT, GL_BACK, GL_FRONT_AND_BACK. Argumentul pname specifică proprietatea materialului, care se defineşte prin apelul funcńiei glmaterial#(). Acest argument poate lua una din următoarele valorile date în tabelul 2. Nume parametru Valoare implicită SemnificaŃie GL_AMBIENT (0.2, 0.2, 0.2, 1.0) reflectanńa (coeficient de reflexie) ambientală GL_DIFFUSE (0.8, 0.8, 0.8, 1.0) reflectanńa de difuzie GL_AMBIENT_AND_DIFFUSE reflectanńa ambientală şi de difuzie GL_SPECULAR (0.0, 0.0, 0.0, 1.0) reflectanńa speculară GL_SHININESS 0.0 exponentul de reflexie speculară GL_EMISSION (0.0, 0.0, 0.0, 1.0) intensitatea luminii emise GL_COLOR_INDEXES (0,1,1) indicii culorilor ambientală, difuză şi speculară Tabelul 2 5
Lucrarea 8 FuncŃiile glmateriali() şi glmaterialf() se folosesc numai pentru setarea strălucirii (GL_SHININESS) la valoarea dată prin argumentul param. FuncŃiile glmaterialiv() şi glmaterialfv() se folosesc pentru specificarea celorlalte proprietăńi. Dacă argumentul pname este GL_COLOR_INDEX atunci param este un pointer la un vector de trei valori de tip întreg, care conńine indicii culorilor ambientală, de difuzie şi speculară ale materialului. În celelalte situańii, param este un pointer la un vector de patru valori de tip întreg sau cu virgulă flotantă, care sunt componentele roşu, verde, albastru şi alpha (transparenńă) ale componentei de reflexie specificate prin parametrul pname (ambientală, difuză, speculară, emisie). Reflexia difuză şi ambientală se specifică de cele mai multe ori cu aceeaşi culoare (aşa cum sunt suprafeńele reale) folosind parametrul GL_AMBIENT_AND_DIFFUSE în apelul funcńiei glmaterial#(). Specificarea culorii produse de reflexia speculară se face prin parametrul GL_SPECULAR, iar dimensiunea şi strălucirea zonei prin parametrul GL_SHININESS. Se poate observa că modelul OpenGL de reflexie permite adăugarea unei componente emisive a luminii reflectate de o suprafańă. Componenta de emisie a unei suprafeńe se specifică prin parametrul GL_EMISSION. Acest efect este folosit pentru simularea lămpilor sau a altor surse de lumină din scenă. FuncŃia glmaterial#() defineşte proprietăńile materialului curent, care se aplică tuturor vârfurilor introduse după acesta prin funcńiile glvertex#()sau prin diferite funcńii de modelare din biblioteca GLUT (de exemplu glutsolidsphere()). ProprietăŃile materialului curent se menńin până la următorul apel al funcńiei glmaterial#(). Calculele de iluminare se pot executa diferit pentru feńele orientate direct (GL_FRONT) şi cele orientate invers (GL_BACK). Un exemplu de definire a unui material este dat prin următoarele instrucńiuni: GLfloat mat_ambient[] = 1.0, 0.0, 0.0, 1.0 ; GLfloat mat_diffuse[] = 1.0, 0.0, 0.0, 1.0 ; GLfloat mat_specular[] = 1.0, 1.0, 1.0, 1.0 ; GLfloat mat_shininess = 50.0; glmaterialfv(gl_front, GL_AMBIENT, mat_ambient); glmaterialfv(gl_front, GL_DIFFUSE, mat_diffuse); glmaterialfv(gl_front, GL_SPECULAR, mat_specular); glmaterialf(gl_front, GL_SHININESS, mat_shininess); 4. Modele de umbrire a suprafeńelor 4.1 Tipuri de modele de umbrire utilizate în OpenGL Prin model de umbrire (shadding) înńelegem un model prin care de determină culoarea de afişare a unui obiect. Modele de umbrire mai sunt numite şi modele de colorare. În OpenGL sunt implementate două modele de umbrire (de colorare): umbrire constantă sau poligonală; umbrire Gouraud. Modelul de umbrire se defineşte prin apelul funcńiei: 6
glshademodel(glenum mode); unde argumentul mode poate lua una din valorile GL_FLAT, pentru modelul de umbrire poligonală, sau GL_SMOOTH, pentru modelul de umbrire Gouraud. Valoarea implicită este GL_SMOOTH. În cazul în care nu este validat sistemul de iluminare (prin apelul funcńiei glenable(gl_lighting)) culoarea care se atribuie vârfurilor primitivelor geometrice este culoarea curentă, setată prin apelul unei funcńii glcolor#(). Dacă se defineşte modelul de umbrire poligonală (GL_FLAT), primitivele geometrice se generează de culoare constantă (culoarea curentă întâlnită la primul vârf introdus prin funcńia glvertex#()). În cazul modelul de umbrire Gouraud (GL_SMOOTH) culorile definite în vârfuri se folosesc pentru calculul intensităńii culorilor pixelilor primitivei geometrice prin interpolare liniară. Culoarea fiecărui vârf este tratată individual. Pentru un segment de dreaptă, culoarea se obńine prin interpolarea culorilor vârfului. Pentru un poligon, culorile punctelor interioare se obńin prin interpolare pe baza culorilor vârfurilor (fig.1). De exemplu, intensitatea punctelor de pe linia y = y se calculează astfel: I P I Q I M s I1 I2 I1 ( y y), y1 y2 I1 I4 I1 ( y y), (1) y1 y4 I P IQ = I P ( xp xm ). x x = 1 = 1 P Q y s 1 2 P M Q y = 4 y s O 3 Fig. 1 Interpolarea liniară a intensităńilor vârfurilor în modelul Gouraud x s 7
Lucrarea 8 5. AplicaŃii Exemplul 1 Să se afişeze un triunghi folosind modelul de colorare (umbrire) Gouraud. Vârfurile triunghiului au culorile roşu, verde şi, respectiv, albastru (fig. 2). Fig. 2 Afişarea unui triunghi folosind modelul Gouraud SoluŃie. Programul care realizează imaginea din fig. 2 este următorul: #include <gl/glut.h> GOURAUD.CPP void init() //selecteaza culoarea de fond glclearcolor(...); glshademodel(...); // void triangle() // se va folosi glbegin() cu parametrul corespunzator pentru //desenarea triunghiului void display() glclear(...); triangle(); glflush(); 8
void reshape (int w, int h) glviewport(0, 0, (GLsizei)w, (GLsizei)h); glmatrixmode(gl_projection); if(w <= h) gluortho2d(0, 30, 0, 30*(GLfloat)h/(GLfloat)w); else gluortho2d(0, 30*(GLfloat)w/(GLfloat)h, 0, 30); glmatrixmode(gl_modelview); int main(int argc, char** argv)... Exemplul 2 Să se evidenńieze diferenńa dintre umbrirea poligonală şi umbrirea Gouraud în cazul unei sfere reprezentate prin reńea de poligoane şi iluminată cu o sursă de lumină. Sursa de lumină se r r r r plasează la infinit, pe direcńia dată de vectorul l = i + j+ k. La apăsarea butonului stâng al mouse-ului sfera se afişează folosind umbrirea poligonală, iar la apăsarea butonului drept sfera se afişează folosind umbrirea Gouraud (fig. 3). Se utilizează proiecńia perspectivă şi apoi proiecńia ortografică. SoluŃie. Programul care generează imaginile din figura 3 este următorul: O parte din funcńii sunt date mai jos. a) b) Fig. 3 a) umbrire poligonală; b) umbrire Gouraud void init() GLfloat mat_specular[] = 1, 1, 1, 1; GLfloat mat_shininess= 50; 9
Lucrarea 8 GLfloat light_position[] = 1, 1, 1, 0; glclearcolor(0.0, 0.0, 0.0, 0.0); glshademodel(gl_smooth); //GL_FLAT pentru culoare uniforma glmaterialfv(gl_front, GL_SPECULAR, mat_specular); glmaterialf(gl_front, GL_SHININESS, mat_shininess); gllightfv(gl_light0, GL_POSITION, light_position); glenable(gl_lighting); glenable(gl_light0); glenable(gl_depth_test); void reshape (int w, int h) glviewport(0, 0, (GLsizei)w, (GLsizei)h); glmatrixmode(gl_projection); gluperspective(60.0, (GLfloat)w/(GLfloat)h, 1, 20.0); /* proiectie ortografica if(w <= h) glortho(-1.5, 1.5, -1.5*(GLfloat)h/(GLfloat)w, 1.5*(GLfloat)h/(GLfloat)w, -10, 10); else glortho(-1.5*(glfloat)w/(glfloat)h, 1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10, 10); */ glmatrixmode(gl_modelview); gltranslatef(0,0,-6); //pentru proiectie perspectiva void mouse(int button, int state, int x, int y)... Exemplul 3 Să se afişeze sfera din exemplul 2, folosind modelul Gouraud. La apăsarea unuia din cele trei butoane ale mouse-ului se vor schimba coeficienńii de difuzie ai materialului: butonul din stânga schimbă componenta roşie, cel din mijloc componenta verde şi cel din dreapta componenta albastră. Pentru modificare parametrilor de material se poate folosi funcńia: void glcolormaterial(glenum face, GLenum mode); Această funcńie actualizează proprietăńile de material specificate de parametrul mode pentru feńele specificate de parametrul face. Astfel, o modificare asupra culorii curente, folosind funcńia glcolor#() actualizează imediat proprietăńile de material specificate. SoluŃie. Principalele funcńii din program sunt prezentate mai jos. 10
GLfloat mat_diffuse[4] = 0.5, 0.5, 0.5, 1.0 ; void init(void) GLfloat mat_specular[] = 1.0, 1.0, 1.0, 1.0 ; GLfloat light_position[] = 1.0, 1.0, 1.0, 0.0 ; glmaterialfv(gl_front, GL_DIFFUSE, mat_diffuse); glmaterialfv(gl_front, GL_SPECULAR, mat_specular); glmaterialf(gl_front, GL_SHININESS, 25.0); gllightfv(gl_light0, GL_POSITION, light_position); glenable(gl_lighting); glenable(gl_light0); glcolormaterial(gl_front, GL_DIFFUSE); glenable(gl_color_material); glenable(gl_depth_test); glshademodel (GL_SMOOTH); glclearcolor (0.0, 0.0, 0.0, 0.0); //implicit void reshape (int w, int h) glviewport (0, 0, (GLsizei) w, (GLsizei) h); glmatrixmode (GL_PROJECTION); gluperspective(60.0, (GLfloat)w/(GLfloat)h, 1, 20.0); /* if (w <= h) glortho (-1.5, 1.5, -1.5*(GLfloat)h/(GLfloat)w, 1.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0); else glortho (-1.5*(GLfloat)w/(GLfloat)h, 1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0); */ glmatrixmode(gl_modelview); gltranslatef(0,0,-6); //pentru proiectie perspectiva void mouse(int button, int state, int x, int y) switch (button) case GLUT_LEFT_BUTTON: if (state == GLUT_DOWN) // schimba rosu mat_diffuse[0] += 0.1; if (mat_diffuse[0] > 1.0) mat_diffuse[0] = 0.0; glcolor4fv(mat_diffuse); glutpostredisplay(); break;... 11
Lucrarea 8 Exemplul 4 Să se realizeze o aplicańie în care o sursă de lumină este rotită în jurul unui tor. Când este apăsat un buton al mouse-ului, sursa de lumină îşi schimbă pozińia cu 30 grade. Sursa de lumină se va reprezenta printr-un mic cub wireframe. SoluŃie. Programul care realizează cerinńele problemei este prezentat mai jos. #include <gl/glut.h> MISCARE_SURSA.CPP static int spin = 0; void init(void) glclearcolor (0.0, 0.0, 0.0, 0.0); glshademodel (GL_SMOOTH); glenable(gl_lighting); glenable(gl_light0); glenable(gl_depth_test); /* - dupa efectuarea transformarii de modelare (glrotated) trebuie resetata pozitia sursei, deoarce este plasata într-o noua pozitie in sistemul universal. - cubul reprezinta pozitia sursei de lumina */ void display(void) GLfloat 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); //transformare de observare glpushmatrix (); glrotated ((GLdouble) spin, 1.0, 0.0, 0.0); gllightfv (GL_LIGHT0, GL_POSITION, position); gltranslated (0.0, 0.0, 1.5); gldisable (GL_LIGHTING); glcolor3f (0.0, 1.0, 1.0); glutwirecube (0.1); glenable (GL_LIGHTING); glpopmatrix (); glutsolidtorus (0.275, 0.85, 8, 15); glpopmatrix (); glutswapbuffers(); glflush (); void reshape (int w, int h) glviewport (0, 0, (GLsizei) w, (GLsizei) h); glmatrixmode (GL_PROJECTION); gluperspective(40.0, (GLfloat) w/(glfloat) h, 1.0, 20.0); 12
glmatrixmode(gl_modelview); void mouse(int button, int state, int x, int y) switch (button) case GLUT_LEFT_BUTTON: if (state == GLUT_DOWN) spin = (spin + 30) % 360; glutpostredisplay(); break; default: break; int main(int argc, char** argv) glutinit(&argc, argv); glutinitdisplaymode (GLUT_DOUBLE GLUT_RGB GLUT_DEPTH); glutinitwindowsize (500, 500); glutinitwindowposition (100, 100); glutcreatewindow (argv[0]); init (); glutdisplayfunc(display); glutreshapefunc(reshape); glutmousefunc(mouse); glutmainloop(); return 0; 13