11/14/2010
FACULTATEA DE AUTOMATICA SI CALCULATOARE
ELEMENTE DE GRAFICA PE CALCULATOR
Laborator 5
ELEMENTE DE GRAFICA PE CALCULATOR
Laborator 5
Iluminare in OpenGL
1. Introducere Un prim pas catre realismul unei scene 3D este introducerea de lumini. Desi fenomenul natural are o complexitate mult mai mare in OpenGL acesta poate fi simplificat pana in punctul in care poate fi descompus in urmatoarele componente : a) Lumina ambientala b) Lumina difuza c) Lumina speculara d) Lumina emisiva
In plus, exista mai multe tipuri de lumini: • Lumina omnidirectionala o Lumineaza in toate directiile si are drept sursa un punct. Poate fi comparata cu soarele sau cu lumina ideala studiata la fizica. • Lumina orientata o Lumineaza intr-o singura directie. Daca sursa este plasata la infinit, atunci volumul luminat este un cilindru. Daca sursa este prezenta in scena, atunci acest volum este un con, al carui unghi si raza pot fi modificate programatic. Ganditi-va la o lumina de tip spot.
2.Tipuri de lumini a) Lumina ambientala Aceasta este lumina care este prezenta in atmosfera „pur si simplu”. Nu provine dintr-o anumita sursa,ci este provenita de la suma tuturor surselor de lumina din scena, prin reflexii repetate. Un exemplu bun este aspectul unui hol care nu are ferestre, dar are usi deschise catre multe camere vecine, luminate. Chiar si acolo unde este umbra, aceasta nu este totala. Datorita luminii reflectate, nicio parte a camerei nu este cu adevarat in intuneric, ci intr-o lumina obscura care totusi permite distingerea vaga a obiectelor. Aceasta este lumina ambientala. Ea nu depinde de orientarea fetelor, si in general un obiect va fi perceput ca o masa amorfa, fara a putea distinge unde incepe o fata si unde se termina o alta.
Pagina 2
ELEMENTE DE GRAFICA PE CALCULATOR
Laborator 5
b) Lumina difuza Aceasta este lumina provenita de la o sursa clar definita. Este formata din mai multe raze care se imprastie in toate directiile. Sursa poate fi plasata la infinit (lumina solara) sau la o distanta calculabila fata de obiect (lumina unui bec). Diferentele se pot observa si in lumea reala. La soare razele sunt paralele, iar la bec emana dintr-un punct fix. Lumina difuza se apropie cel mai mult de majoritatea luminilor din viata reala, reprezentant clasa luminilor cu sursa si directie.
c) Lumina speculara Aceasta este componenta care da stralucire obiectelor. Este efectul care apare atunci cand privim caroseria unei masini bine spalate. Culoarea generala a masinii este sa zicem rosie, dar in anumite locuri aceasta culoare este inlocuita de o stralucire puternica alba. Lumina speculara este asemanatoare unui laser. Razele pleaca paralel din sursa de lumina (de obicei aceeasi cu sursa de lumina difuza), dar nu pot fi percepute decat dintr-o anumita pozitie a observatorului. Din acest motiv daca ne deplasam in jurul masinii de mai sus, vom observa ca se deplaseaza si stralucirea, urmarindu-ne miscarea. d) Lumina emisa Aceasta este lumina pe care un obiect o emite prin el insusi. In OpenGL, aceasta este doar simulata, obiectul neluminand la randul lui alte obiecte. Daca am vrea sa creem o lampa de exemplu, am folosi atat lumina emisa (pentru a lumina becul lampii in sine) cat si o lumina difuza centrata in acest bec, pentru a lumina obiectele din jurul sau, dand iluzia unei lampi care emana lumina. ELEMENTE DE GRAFICA PE CALCULATOR Laborator 6
3. Lumina in OpenGL In OpenGL, toate luminile de mai sus sunt simulate printr-o singura sursa de lumina, cu diversi parametri. Valorile acestor parametri se exprima prin culori. De exemplu, lumina difuza este caracterizata printr-o culoare. Daca aceasta este alb, atunci lumina va fi o lumina alba. Daca aceasta este negru, atunci lumina nu va avea componenta difuza. Luminile in OpenGL pot folosi urmatorii parametri : a) Culoarea ambientala (GL_AMBIENT) Culoarea ambientala a luminii. Aceasta se poate seta pentru fiecare sursa de lumina in parte. Este lumina cu care contribuie aceasta sursa la intreaga lume. Pentru realism, se seteaza la fel cu culoarea difuza. b) Culoarea difuza (GL_DIFFUSE) Componenta cea mai usor vizibila a unei surse de lumina. Ea da culoarea efectiva a luminii. Pentru soare de exemplu, aceasta componenta ar fi un galben pal. c) Culoarea speculara (GL_SPECULAR) Componenta care da stralucire obiectelor. Daca o lumina are aceasta culoare diferita de cea difuza, atunci zonele afectate de razele speculare (care depind de material) vor folosi si aceasta culoare.
Pagina 3
ELEMENTE DE GRAFICA PE CALCULATOR
Laborator 5
d) Pozitia (GL_POSITION) Specifica efectiv pozitia sursei de lumina. Este utila doar la calculul componentelor difuze sispeculare, in mod evident. Atentie, in openGL aceasta componenta este un vector de 4 elemente (x,y,z,w). Daca w este 0, atunci lumina va fi la infinit. (vom seta permanent w = 1 daca nu asta este intentia). Mai mult, veti observa ca OpenGL pastreaza lumina intr-un spatiu diferit celui in care va asteptati sa fie pastrata. Acest aspect va fi discutat la laboratoarele urmatoare. e) Atenuarea Orice lumina se atenueaza cu distanta. Dupa o anumita distanta nu mai putem percepe deloc aceasta lumina. In openGL avem 3 variabile prin care modificam atenuarea : i. GL_CONSTANT_ATTENUATION ( k0 ) ii. GL_LINEAR_ATTENUATION ( k1 ) iii. GL_QUADRATIC_ATTENUATION (k2 ) Daca presupunem distanta de la obiect la lumina cunoscuta si notata cu d, atunci avem: atenuare = 1 / (k0 + k1*distance + k2* distance^2) f) Lumina directionala GL_SPOT_CUTOFF - Unghiul de la varful conului in care sunt proiectate razele GL_SPOT_DIRECTION - Directia luminii GL_SPOT_EXPONENT – Gradul de focalizare a luminii. Intre 0 si 128. Este efectul pe care il obtineti daca invartiti partea superioara a unei lanterne.
4. Materiale Notiunea de material este una foarte apropiata lumii reale. Daca privim in jurul nostru observam cu usurinta ca nu toate obiectele trateaza lumina primita in acelasi fel. Plasticul pare mat. Metalele sunt mai inchise la culoare, dar au zone care stralucesc. Etc. Pentru a simula acest comportament, OpenGL ne pune la dispozitie notiunea de material. Materialele au la randul lor cateva atribute de baza a) Culoarea Ambientala (GL_AMBIENT) Lumina ambientala este reflectata cu aceasta valoare (impreuna cu componenta ambientala a sursei de lumina) b) Culoarea Difuza (GL_DIFFUSE) Lumina difuza este reflectata cu aceasta valoare Nota : In lumea reala sunt deosebit de rare (practic nu exista) materiale care sa aibe valori diferite ale componentelor difuze si ambientale. De obicei se seteaza impreuna si nu se modifica disparat : GL_AMBIENT_AND_DIFFUSE Pagina 4
ELEMENTE DE GRAFICA PE CALCULATOR
Laborator 5
c) Culoarea Speculara (GL_SPECULAR) Lumina speculara este reflectata cu aceasta valoare. De exemplu la un diamant, culoarea difuza este alb, dar culoarea speculara poate fi albastra, rosie, etc, in functie de culoarea cu care piatra pretioasa reflecta razele. d) Stralucire ( GL_SHININESS) Aceasta este o valoare care modifica focalizarea razei speculare. O valoare maxima ne spune ca exista o singura raza speculara (practic, ochiul trebuie sa fie intr-o pozitie fixa pentru a vedea lumina speculara). Daca observatorul se deplaseaza cat de putin, nu va mai vedea aceasta lumina. O valoare mica da voie observatorului sa se deplaseze intr-o raza mai mare, fara a pierde componenta speculara. Un CD de exemplu are componenta shininess foarte mare. Razele de lumina speculara sunt foarte subtiri. La fel un ceas metalic. O poleiala de bomboana pe de alta parte, are o stralucire mica. Variatii in pozitia observatorului provoaca variatii mici in modul cum se percepe obiectul. e) Emisie ( GL_EMISSION ) Aceasta este o setare prin care se da incandescenta unui obiect. Acesta va parea ca lumineaza cu culoarea specificata, indiferent de celelalte lumini care il afecteaza.ELEMENTE DE GRAFICA PE
5. Iluminarea in OpenGL Pentru a pune cu succes in scena lumini in OpenGL, trebuie urmati cu strictete urmatorii pasi : a) Initializarea mediului glEnable(GL_LIGHTING) : fara aceasta functie, OpenGL nu va face deloc calcule de iluminare. b) Aprinderea luminilor glEnable(GL_LIGHT0) : acesta functie aprinde sursa de lumina glEnable(GL_LIGHT1) : acesta functie aprinde sursa de lumina cu numarul 2
cu
numarul
1
.... glEnable(GL_LIGHT7) : acesta functie aprinde sursa de lumina nr. 8(ultima) Toate proprietatile luminii pe care le vom da in continuare se vor seta in una din aceste 8 lumini. Acesta este numarul maxim de lumini intr-o scena OpenGL (in anumite implementari acest numar poate fi mai mare). Cu toate acestea, mai exista o sursa in scena introdusa automat chiar daca nu sunt aprinse aceste lumini: Lumina Ambientala Globala GLfloat lmodel_ambient[] = { 0.2, 0.2, 0.2, 1.0 }; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); Aceasta este lumina prin care se pot vedea obiectele chiar daca noi nu adaugam explicit lumina, ea defineste o lumina ambientala de baza,. Pagina 5
ELEMENTE DE GRAFICA PE CALCULATOR
Laborator 5
c) Setarea modelului de iluminare glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE) aceasta functie seteaza pozitia ochiului in (0,0,0). Avem nevoie de ea atunci cand calculam reflexile speculare. Deobicei observatorul se considera a fi la infinit astfel incat unghiul format de raza incidenta pe un punct si de linia observatorpunct depinde doar de raza incidenta. glLightModeli(LIGHT_MODEL_TWO_SIDE, GL_TRUE) aceasta functie spune openGL-ului sa faca toate calculele si pentru fetele considerate ca sunt cu spatele la lumina. Deobicei aceste fete sunt orientate spre interiorul corpurilor deci nu avem nevoie de lumina pe ele. Insa daca vrem sa iluminam si partea interioara a unei jumatati de sfera, trebui sa setam si acest parametru. glShadeModel(GL_SMOOTH / GL_FLAT) Acesta nu face parte neaparat din modelul de iluminare, insa e destul de important in acest context. Se seteaza cu glShadeModel si poate fi de doua feluri: smooth sau flat. Modul flat pune aceiasi culoare pe toata fata, in timp ce modul shade interpoleaza valorile din colturi. Trebuie sa fim atenti la cazul in care o lumina de tip spot cade pe centrul unui obiect fara sa ii atinga colturile. Daca se intampla asta, lumina va fi practic ignorata. d) Setarea parametrilor obiectelor Dupa ce am parcurs pasii de mai sus, putem sa incepem sa setam parametrii efectivi ai luminilor. Ne alegem una din cele 8 surse de lumina, sa zicem GL_LIGHT0, si vom opera asupra ei. Un exemplu simplu - pentru a seta un parametru oarecare din cei care urmeaza, se apeleaza un cod ca cel de mai jos: GLfloat light_ambient[] = { 0.5, 0.5, 0.5, 1.0 }; glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); Acest cod seteaza propietatea GL_AMBIENT la valorile precizate pentru sursa de lumina GL_LIGHT0. Cei 4 parametrii reprezinta valorile RGBA ale luminii – intre 0 si 1. RGB este destul de clar ce inseamna, alfa este folosit daca vrem sa facem, de exemplu, culoarea luminii mai importanta decat culoarea obiectului. Daca obiectul are alfa mai mic decat 1.0, atunci culoarea naturala a obiectului va fi mai putin importanta decat culoarea luminii atunci cand se va calcula valoarea luminii reflectate. Se pot folosi in loc de GL_AMBIENT toti parametri definiti mai sus, si anume : i. GL_DIFFUSE ii. GL_POSITION iii. GL_SPECULAR iv. GL_SPOT_CUTOFF Pagina 6
ELEMENTE DE GRAFICA PE CALCULATOR
Laborator 5
v. GL_SPOT_DIRECTION vi. GL_LINEAR_ATTENUATION Etc e) Setare normale Normalele sunt vitale pentru o afisare corecta a luminilor. Aceasta informatie transmite catre OpenGL directia in care este orientata o fata, pentru a sti daca aceasta este sau nu luminata. Pentru a se trata corect informatiile legate de normala, vertecsii care formeaza un poligon trebuiesc oferiti in sens trigonometric. Normalele se seteaza cu functia : glNormal3f(x, y, z); Unde x,y si z sunt coordonatele normalei. Normala se poate specifica o singura data pentru un singur poligon. Exemplu : glNormal3f(1, 0, 0); glVertex3f(1, -1, -1); glVertex3f(1, 1, -1); glVertex3f(1, 1, 1); glVertex3f(1, -1, 1); Exemplul de mai sus seteaza in mod corect normala si vertecsii unui quad paralel cu planul YOZ si plasat la distanta de 1.0f pe axa OX;
f) Exemplu de setare lumini nr light_position[] = { 0.0, 100.0, 0.0, 1.0 }; //seteaza pozitia nr light_ambient [] = { 0.9, 0.4, 0.0, 1.0 }; //seteaza componenta ambientala nr light_difusion[] = { 0.9, 0.4, 0.0, 1.0 }; //seteaza componenta de difuzie nr light_specular[] = { 0.9, 0.4, 0.0, 1.0 }; //seteaza componenta speculara nr direction [] = { 1.0, -1.0, 1.0}; //seteaza directia spotului glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular); glLightfv(GL_LIGHT1, GL_AMBIENT , light_ambient); glLightfv(GL_LIGHT1, GL_DIFFUSE , light_difusion); glLightfv(GL_LIGHT1, GL_POSITION, light_position); glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, direction); glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, 45.0); Pagina 7
ELEMENTE DE GRAFICA PE CALCULATOR
Laborator 5
glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, 3.0); Acest exemplu seteaza o lumina rosiatica (0.9 > 0.4), pozitionata la inaltimea 100 (observati ca ultimul parametru al pozitiei nu este 0, deci avem lumina pozitionala) si apoi ii definim si propietati de spot. Directia este in jos, unghiul de deschidere totala va fi 45*2=90 si exponentul este 3 ca sa concentram lumina catre interiorul spotului. Matematic vorbind, intensitatea luminii intr-o anumita parte a spotului, va fi cos(unghi(raza in cadrul spotului, directia generala a spotului))) la puterea a 3-a. g) Exemplu de setare material GLfloat mat_diffuse[] = { 0.1, 0.5, 0.8, 1.0 }; GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat low_shininess[] = { 5.0 }; glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess); Acest exemplu seteaza un material cu o culoare turcoaz, stralucire scazuta si lumina speculara alba. Se poate experimenta cu diverse valori pentru a observa exact efectul fiecarui parametru asupra aspectului scenei.
Pagina 8
ELEMENTE DE GRAFICA PE CALCULATOR
Laborator 5
Anexa 1 : Exemplu Materiale Plecam de la o scena standard, cu o lumina de culoare difuza alba, ambientala neagra, speculara alba, atenuari la valorile standard openGL, care contine o sfera. Sfera are un material de culoare difuza rosie, culoare ambientala rosie, culoare speculara neagra, shininess 100 Mai jos nu s-au modificat decat variabilele aferente materialului.
stare initiala
culoare speculara alba
shininess mai mic
culoare speculara albastra
culoare de emisie verzuie
Pagina 9
ELEMENTE DE GRAFICA PE CALCULATOR
Laborator 5
Anexa 2 : Exemplu Lumini Plecam de la o scena standard, cu o lumina de culoare difuza alba, ambientala neagra, speculara alba, atenuari la valorile standard openGL, care contine o sfera. Sfera are un material de culoare difuza rosie, culoare ambientala rosie, culoare speculara neagra, shininess 100. Mai jos nu s-au modificat decat variabilele aferente luminii.
lumina ambientala : 1. Albastru inchis 2. Verde puternic 3. Gri deschis
lumina difuza 4. Alb 5. Alb puternic (peste 1,1,1) 6. Albastru
lumina speculara 7. Alb 8. Alb puternic (peste 1,1,1) 9. Albastru
spot cutoff 10. 45 o 11. 20 o 12. 5o
spot exponent 13. 0 14. 64 15. 128
Pagina 10
ELEMENTE DE GRAFICA PE CALCULATOR
Laborator 5
Anexa 3 : Exemplu utilizare De ce sunt utili parametri de mai sus? Ajuta la simularea cat mai exacta a lumii reale. Puteti observa cateva exemple mai jos, folosind exclusiv elementele discutate anterior.
Sarma : stralucire 55, culoare speculara alba puternica, ambient negru, difuz negru
Piele umana : stralucire 10, culoare speculara maro inchis, ambient verde deschis, difuz roz palid, emisie maro foarte inchis
Guma de creion : stralucire 0, ambient si difuz verde, specular alb Suport metalic : stralucire 30, ambient si difuz maro inchis, specular alb
Bec : stralucire 10, culoare speculara galben foarte puternic, ambient si difuz alb, emisie alb galbui
Pagina 11
ELEMENTE DE GRAFICA PE CALCULATOR
Laborator 5
Anexa 4 : Clase in C++
1. Derivare • Pentru a deriva o clasa fiu dintr-o clasa parinte, se foloseste : class fiu : parinte { }
2. Supraincarcare • Presupunand ca avem in clasa parinte o metoda metoda(), care este definita si in fiu, presupunem ca sar putea sa dormi la un moment dat sa apelam fiu::metoda() desi referinta pe care noi o avem (pointerul) este de tip parinte. Pentru a face acest lucru, folosim virtual :
class parinte { void metoda() { printf(„parinte”); } }
class parinte { virtual void metoda() { printf(„parinte”); } }
class fiu : parinte { void metoda() { printf(„fiu”); } } fiu *f = new fiu(); parinte *p = f; p.metoda();
class fiu : parinte { void metoda() { printf(„fiu”); } } fiu *f = new fiu(); parinte *p = f; p.metoda();
REZULTAT : „parinte”
REZULTAT : „fiu”
Se pune bineinteles problema de ce am vrea sa facem asa ceva. Motivele sunt destul de evidente. Daca avem o clasa de tip Object3D, atunci vrem sa tinem un vector de pointeri la astfel de obiecte, pentru care sa apelam diverse functii generice (de exemplu Draw() ). Daca derivate ale clasei Object3D supraincarca aceasta functie, atunci putem avea obiecte de orice tip, cu metode proprii, dar care se executa toate printr-un simplu apel de tipul Object3D::Draw(); Pagina 12
ELEMENTE DE GRAFICA PE CALCULATOR
Laborator 5
3. Variabile statice O variabila statica in cadrul unei clase este o variabila care primeste o singura valoare, indiferent de cate ori ar fi instantiata clasa Se foloseste atunci cand exista variabile care sunt necesare tuturor obiectelor din acea clasa (un minim si maxim, un string de eroare, etc ).
Anexa 5 : Laborator 5 Scurta descriere a claselor din laborator si a ceea ce se poate face cu ele : • Vector3D / Vector4D o Clasa de baza pentru operatii pe vectori. Se poate extinde pentru a contine operatii mai complicate, cum ar fi inmultirea cu matrici. o Pentru a transforma un Vector*D intr-o matrice de floati se foloseste functia .Array()
• Object3D o Clasa de baza pentru desenarea obiectelor 3D. Contine o functie customDraw() care poate fi supraincarcata intr-o clasa copil si va fi apelata de fiecare data, functie de tipul obiectului
• Plane o Clasa derivata din Object3D care deseneaza un plan • Light o Clasa derivata din Object3D care plaseaza o lumina in scena. Foloseste functiile din clasa parinte pentru a afisa pe ecran un placeholder in pozitia luminii
Pagina 13