This is an old revision of the document!


Laboratorul 07

Iluminare folosind GLSL

Lumina este un factor foarte important in redarea cat mai realista a unei scene 3D. Impreuna cu proprietatile de material ale unui obiect, lumina determina modalitatea in care obiectul este afisat in scena 3D.

Exista mai multe modele empirice pentru calculul reflexiei luminii intr-un punct al unei suprafete: Phong (1975), Blinn-Phong (1977), Oren-Nayar (1994), Cook-Torrance (1981), Lambert (1760), etc (la curs veti discuta despre modelul Lambert si despre modelul Phong).

De asemenea, exista mai multe modele de shading, care specifica metoda de implementare a modelului de calcul al reflexiei luminii. Mai exact, modelul de shading specifica unde se evalueaza modelul de reflexie. Daca vrem sa calculam iluminarea pentru o suprafata poligonala:

  • in modelul de shading Lambert, se calculeaza o singura culoare pentru un poligon al suprafetei
  • in modelul de shading Gouraud (1971), se calculeaza cate o culoare pentru fiecare varf al unui poligon. Apoi, culorile fragmentelor poligonului se calculeaza prin interpolare intre varfuri (interpolarea liniara a culorilor varfurilor, pentru fragmentele de pe laturi si interpolare liniara intre culorile capetelor fiecarui segment interior, pentru fragmentele interioare poligonului). Calcularea culorilor varfurilor se poate efectua in vertex shader.
  • in modelul de shading Phong (1975), se calculeaza cate o normala pentru fiecare varf al unui poligon. Apoi, pentru fiecare fragment se determina o normala prin interpolare intre normalele din varfuri. Astfel, se calculeaza o culoare pentru fiecare fragment al unui poligon (in fragment shader)

Figura 1. Diferite modele de shading: Lambert (o culoare per primitiva), Gouraud (o culoare per varf), Phong (o culoare per fragment)

In acest laborator sa va discuta modelul de shading Gouraud peste modelul de reflexie Phong.

Modelul Phong pentru calculul reflexiei luminii

Ca model de reflexie vom prezenta in continuare un model care extinde modelul de reflexie Phong si care contine toate cele 4 componente care pot fi folosite pentru a calcula iluminarea. Pentru a obtine astfel culoarea intr-un punct al unei suprafete vom avea urmatoarele componente :

  • Componenta emisiva
  • Componenta ambientala
  • Componenta difuza
  • Componenta speculara

Contributia fiecarei componente este calculata ca o combinatie dintre proprietatile de material ale obiectului (factorul de stralucire, culoarea materialului) si proprietatile sursei de lumina (culoarea sursei de lumina, pozitia sursei de lumina).

Astfel culoarea finala a unui punct apartinand unei suprafete este:

     culoare = emisiva + ambientala + difuza + speculara

In cele ce urmeaza prezentam pe scurt ce reprezinta cele 4 componente si cum pot fi calculate.

Componenta emisiva

Aceasta reprezinta lumina emisa de un obiect si nu tine cont de nici o sursa de lumina. Daca un obiect care are o anumita culoare emisiva s-ar afla intr-o scena complet intunecata atunci el ar aparea exact cu aceasta culoare.

O utilizare des intalnita pentru componenta emisiva este aceea de a simula stralucirea unui obiect.

Avem astfel:

     emisiva = Ke

  • Ke – culoarea emisiva a materialului

Componenta ambientala

Aceasta reprezinta lumina reflectata de catre obiectele din scena de atat de multe ori incat pare sa vina de peste tot.

Astfel lumina ambientala nu vine dintr-o directie anume, aparand ca si cum ar veni din toate directiile. Din aceasta cauza componenta ambientala este independenta de pozitia sursei de lumina.

Componenta ambientala depinde de culoarea de material ambientala a suprafetei obiectului si de culoarea ambientala a luminii.

Similar componentei emisive, componenta ambientala este o constanta (se poate extinde modelul atribuind fiecarei lumini din scena o culoare ambientala).

Avem astfel:

     ambientala = Ka * culoareaAmbientalaGlobala

  • Ka – culoarea ambientala de material a obiectului
  • culoareaAmbientalaGlobala – culoarea ambientala a luminii

Componenta difuza

Aceasta reprezinta lumina reflectata de suprafata obiectului in mod egal in toate directiile.

Cantitatea de lumina reflectata este proportionala cu unghiul de incidenta al razei de lumina cu suprafata obiectului.

Avem astfel:

     difuza = Kd * culoareLumina * max (N * L, 0)

  • Kd - culoarea de material difuza a obiectului
  • culoareLumina – culoarea difuza a luminii
  • N – normala la suprafata (normalizata)
  • L – vectorul directei luminii incidente (normalizat)
  • $max(N\cdot L, 0)$ – produsul scalar $N\cdot L$ reprezinta masura unghiului dintre acesti 2 vectori; astfel daca i este mai mare decat $\pi/2$ valoarea produsului scalar va fi mai mica decat 0, acest lucru insemnand ca suprafata nu primeste lumina ( sursa de lumina se afla in spatele suprafetei ) si de aici si formula care asigura ca in acest caz suprafata nu primeste lumina difuza

Componenta speculara

Un reflector perfect, de exemplu o oglinda, reflecta lumina numai intr-o singura directie $R$, care este simetrica cu $L$ fata de normala la suprafata. Prin urmare, doar un observator situat exact pe directia respectiva va percepe raza reflectata.

Componenta speculara reprezinta lumina reflectata de suprafata obiectului numai in jurul acestei directii, $R$.

In modelul Phong se aproximeaza scaderea rapida a intensitatii luminii reflectate atunci cand $\alpha$ creşte prin $cos^n \alpha$, unde $n$ este exponentul de reflexie speculară al materialului (shininess).

Astfel avem: $speculara = K_s \cdot culoareLumina \cdot primesteLumina \cdot (max(V\cdot R, 0))^n$

     speculara = Ks * culoareLumina * primesteLumina * pow(max(dot(V, R), 0), n) # GLSL

O altă formulare a modelului Phong se bazează pe vectorul median, notat cu $H$. El face unghiuri egale cu $L$ şi cu $V$. Dacă suprafaţa ar fi orientată astfel încât normala sa să aibă direcţia lui $H$, atunci observatorul ar percepe lumina speculară maximă (deoarece ar fi pe direcţia razei reflectate specular).

Termenul care exprimă reflexia speculară este în acest caz: $(N_u \cdot H_u)^n$

     pow(dot(Nu, Hu), n) # GLSL

  • $H_u = (L_u + V_u)$ (normalizat)

Atunci când sursa de lumină şi observatorul sunt la infinit, utilizarea termenului $N_u\cdot H_u$ este avantajoasă deoarece $H_u$ este constant.

Dupa cum se observa, fata de celelalte 3 componente, componenta speculara depinde si de pozitia observatorului. Daca observatorul nu se afla intr-o pozitie unde poate vedea razele reflectate atunci nu va vedea reflexie speculara pentru zona respectiva. De asemenea, nu va vedea reflexie speculara daca lumina se afla in spatele suprafetei.

Tinand cont de toate acestea avem pentru componenta speculara urmatoarea formula: $speculara = K_s \cdot culoareLumina \cdot primesteLumina \cdot (max(N\cdot H, 0)^n $

     speculara = Ks * culoareLumina * primesteLumina * pow(max(dot(N, H), 0), n) # GLSL

  • Ks - culoarea de material speculara a obiectului
  • culoareLumina – culoarea speculara a luminii
  • N – normala la suprafata (normalizata)
  • L – vectorul directei luminii incidente (normalizat)
  • H – vectorul median (normalizat)
  • primesteLumina – 1 daca $N\cdot L$ este mai mare decat 0; sau 0 in caz contrar

Atenuarea intensitatii luminii

Atunci când sursa de lumină punctiformă este suficient de îndepărtată de obiectele scenei vizualizate, vectorul L este acelaşi în orice punct. Sursa de lumină este numită în acest caz direcţională. Aplicând modelul pentru vizualizarea a două suprafeţe paralele construite din acelaşi material, se va obţine o aceeaşi intensitate (unghiul dintre L şi normală este acelaşi pentru cele două suprafeţe). Dacă proiecţiile suprafeţelor se suprapun în imagine, atunci ele nu se vor distinge. Aceasta deoarece în model nu se ţine cont de faptul că intensitatea luminii descreşte proporţional cu inversul pătratului distanţei de la sursa de lumină la obiect. Deci, obiectele mai îndepărtate de sursă sunt mai slab luminate. O posibilă corecţie a modelului, care poate fi aplicata pentru surse pozitionale (la distanta finita de scena) este:

   culoareObiect = emisiva + ambientala + factorAtenuare * ( difuza + speculara )

  • factorAtenuare = 1/d^2 este o funcţie de atenuare
  • d este distanţa de la sursă la punctul de pe suprafaţă considerat

Corecţia de mai sus nu satisface cazurile în care sursa este foarte îndepărtată. De asemenea, dacă sursa este la distanţă foarte mică de scenă, intensităţile obţinute pentru două suprafeţe cu acelaşi unghi i, între L şi N, vor fi mult diferite.

O aproximare mai bună este următoarea:

     factorAtenuare = 1/(Kc + Kl*d + Kq*d2)

  • Kc - factorul de atenuare constant
  • Kl - factorul de atenuare liniar
  • Kq - factorul de atenuare patratic

Detalii de implementare

Pentru simplitate, in cadrul laboratorului vom implementa modelul de shading Gouraud (in vertex shader):

  • Se vor calcula practic doar componentele difuze si speculare asa cum au fost prezentate anterior; componenta emisiva nu va fi folosita iar calculul componentei ambientale va fi simplificat astfel incat sa nu mai trebuiasca trimis nimic din program catre shader (mai multe detalii la punctul 3).
  • Vom folosi ca materiale pentru obiecte doar culoarea de material difuza si speculara (transmise din program catre shader) : Ks si Kd.
  • In shader vom aproxima lumina ambientala cu o culoareAmbientalaGlobala care va fi o constanta in shader iar in loc de Ka (constanta de material ambientala a obiectului) vom folosi Kd (constanta de material difuza a obiectului).
  • Culoarea luminii (difuza si speculara) va fi alba, deci culoareLumina va fi 1 si nu va mai fi necesar sa fie folosita la inmultirile din formulele de calcul pentru componentele difuza si speculara.
  • Calculele de iluminare se vor face in world space deci inainte de fi folosite, pozitia si normala vor trebui aduse din object space in world space. Acest lucru se poate face astfel:
    • pentru position:
      vec3 world_pos = (model_matrix * vec4(v_position,1)).xyz;
    • pentru normala:
      vec3 world_normal = normalize( mat3(model_matrix) * v_normal );
  • Vectorul directiei luminii L:
    vec3 L = normalize( light_position - world_pos );
  • Vectorul directiei din care priveste observatorul V:
    vec3 V = normalize( eye_position - world_pos );
  • Vectorul median H:
    vec3 H = normalize( L + V );

Functii GLSL utile care pot fi folosite pentru implementarea modelului de iluminare

  • normalize(V) – normalizeaza vectorul V
  • normalize(L+V) – normalizeaza vectorul obtinut prin L+V
  • normalize(X1-X2) - returneaza un vector de directie normalizat avand doua puncte X1 si X2
  • dot(N,L) – calculeaza produsul scalar dintre N si L
  • pow(L, shininess) – calculeaza L la puterea shininess
  • max(N,V) – returneaza maximul dintre N si V
  • distance(P1,P2) – returneaza distanta euclidiana dintre punctele P1 si P2
  • reflect(L,N) - calculeaza vectorul de reflexie pornind de la incidenta L si normala N

Cerinte laborator

tasta F5 - reincarca shaderele in timpul rularii aplicatiei. Nu este nevoie sa opriti aplicatia intrucat shaderele sunt compilate si rulate de catre placa video si nu au legatura cu codul sursa C++ propriu zis.

  1. Completati functia RenderSimpleMesh astfel inca sa trimiteti corect valorile uniform catre Shader:
    • Pozitia luminii
    • Pozitia camerei
    • Proprietatile de material (Kd, Ks, Shininess, Culoare obiect)
  2. Implementati iluminarea in Vertex Shader
    • Vectorii N, V, L si pozitia in spatiul global
    • Componenta ambientala
    • Componenta difuza
    • Componenta speculara (atat in varianta de baza cat si folosind vectorul median)
    • Factor de atenuare
    • Culoarea finala
  3. Completati Fragment Shaderul astfel incat sa aplicati iluminarea calculata in Vertex Shader
  4. Colorati sfera si planul din scena (de ex: sfera - albastru, planul - gri)
egc/laboratoare/07.1510175725.txt.gz · Last modified: 2017/11/08 23:15 by florin_eugen.iancu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0