This is an old revision of the document!
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:
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.
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 :
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.
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
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
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)
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
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
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 )
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.
Pentru simplitate, in cadrul laboratorului vom implementa modelul de shading Gouraud (in vertex shader):
vec3 world_pos = (model_matrix * vec4(v_position,1)).xyz;
vec3 world_normal = normalize( mat3(model_matrix) * v_normal );
vec3 L = normalize( light_position - world_pos );
vec3 V = normalize( eye_position - world_pos );
vec3 H = normalize( L + V );
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.
RenderSimpleMesh
astfel inca sa trimiteti corect valorile uniform catre Shader: