This is an old revision of the document!


Laboratorul 06

Reamintire!!! Puteți prezenta rezolvările cerințelor de până la 2 laboratoare, în fiecare săptămână. De exemplu, puteți prezenta laboratorul curent și pe cel din săptămâna anterioară, în totalitate sau parțial, inclusiv punctajul pentru cerința bonus :) .

Pentru rezolvarea cerințelor din cadrul acestui labroator:

  1. Descărcați framwork-ul de laborator și copiați, din arhiva descărcată, directorul Lab6, în interiorul directorului gfx-framework-ppbg\src\lab din versiunea voastră de proiect.
  2. Adăugați în fișierul lab_list.h, linia #include “lab/lab6/lab6.h”.
  3. Folosiți din nou utilitarul CMake pentru a regenera proiectul. Pentru a vă reaminti procesul de realizare a setup-ului, puteți să reconsultați pagina dedicată acestui lucru.

Modele de iluminare

In laboratoarele anterioare, am analizat modalitatea prin care se poate desena pe ecran geometria unor modele 3D. Pana in acest moment, culorile atribuite pixelilor in care a fost discretizata suprafata geometriei au fost alese artificial prin diferite abordari, precum interpolarea intre culorile varfurilor. Deoarece ochiul uman “vede” doar lumina, culoarea unui pixel in care a fost discretizata o suprafata, trebuie sa se calculeze pe baza influentei sursei lumina asupra punctului de pe suprafata. Pentru acest proces, se introduce in procesul de desenare, conceptul de sursa de lumina. Exista mai multe tipuri de astfel de surse:

  • Sursa de lumina punctiforma, ce are o pozitia in spatiul lume si imprastie lumina uniform in toate directiile in jurul acestei pozitii
  • Sursa de lumina de tip spot, similara cu o lanterna, ce are o pozitie in spatiul lume si imprastie lumina de-alungul unei singure directii, de la aceasta pozitie.

Calcularea influentei unei sursa de lumina, de orice tip, asupra unui punct de pe o suprafata se realizeaza prin simularea procesului de transport al luminii de la pozitia sursei, prin reflexie pe suprafata, in pozitia punctului de calcul, la pozitia observatorului. Abordarea de simulare a acestui proces de simulare a transportului luminii poarta numele de model de iluminare sau de model de reflexie.

In general, in toate modelele de iluminare, influenta luminii asupra unui punct este impartita in 4 componente:

  • Componenta emisiva, reprezentata de lumini care este emisa direct de catre suprafata. Este vorba despre suprafetele ce emit lumina, precum suprafata unui bec sau a ecranului unui televizor.
  • Componenta de reflexie indirecta a luminii, ce se refera la procesul de transport al luminii, de la o sursa, prin reflexia pe mai multe, secvential, la pozitia observatorului.
  • Componenta de reflexie difuza, ce se refera la transportul luminii de la o sursa, prin reflexia pe exact o singura suprafata, intr-un punct, la pozitia observatorului.
  • Componenta de reflexie stralucitoare, ce se refera, similar cu cea de reflexie difuza, la transportul luminii de la o sursa, prin reflexia pe o singura suprafata, intr-un punct, la pozitia observatorului.

Diferenta dintre ultimele doua componente este data de comportamentul de reflexie, respectiv o reflexie difuza si o reflexie oglinda.

Deoarece lumina este aditiva, cu cat mai multi fotoni ajung in ochii nostri, cu atat lumina este mai “puternica” :), rezultatul final al influentei iluminarii intr-un punct este dat de suma celor 4 componente:

influenta_finala = componenta_emisiva + componenta_indirecta +
                   componenta_difuza + componenta_stralucire; # GLSL

Componenta emisiva

In situatia in care ne referim strict la transportul luminii de la suprafata la pozitia observatorului, aceasta componenta se poate aproxima printr-o distributie uniforma a imprastierii luminii de la suprafata in toate directiile, astfel ca se poate folosi o valoare constanta.

In situatia in care dorim sa simulam procesul de transport al luminii de la o suprafata ce emite lumina, prin reflexie pe o alta suprafata, la pozitia observatorului, procesul este devine foarte complex. Exista abordari pentru simularea lui, dar in general in aplicatii grafice in timp real se evita astfel de efecte vizuale. O metoda

Componenta indirecta a iluminarii

In general, este precalculata in aplicatiile grafice in timp real si se evita utilizarea pentru un numar mare de obiecte dinamice. Odata cu aparitia procesoarelor grafice ce au arhitecturi de ray-tracing, se folosesc astfel de tehnici pentru simularea transportului luminii de la o sursa, ce ajunge prin reflexii multiple pe mai multe suprafete, secvential, la pozitia observatorului.

Componentele de reflexie directa

Acestea se refera la transportul luminii de la pozitia unei surse, prin reflexie pe o suprafata la pozitia observatorului. Pentru comoditate, se imparte acest tip de reflexie in doua componente distincte:

Componenta de reflexie difuza

Aceasta componenta se refera la cantitatea de lumina ce este imprastiata uniform prin reflexie pe o suprafata in toate directiile din jurul punctului de pe suprafata, deasupra ei.

Componenta de reflexie oglinda

Aceasta componenta se refera la cantitatea de lumina ce este reflectata de-alungul directiei de reflexie simetrica fata de directia de incidenta a luminii cu directia vectorului normal. Aceasta componenta este cunoscuta sub numele de componenta speculara. Termenul speculum in limba latina se traduce in limba romana cu termenul de oglinda :) .

Atenuarea intensitatii iluminarii pe baza de distanta

In momentul in care sursa de lumina a un fascicul difuz se departeaza de un obiect, prin procesul de difuzie, cantitatea de lumina emisa se pastreaza, dar obiectul primeste o cantitate mai mica de lumina. Calculul acestui fenomen se realizeaza pe baza de distanta fata pozitia sursei de lumina si pozitia pentru care se calculeaza iluminarea.

Laborator

In practica, inclusiv in cadrul acestui laborator, se utilizeaza simulari ale fenomenelor optice.

Componenta emisivă

componenta_emisiva = Ke; # GLSL

  • Ke – culoarea emisivă a materialului

Componenta indirecta a iluminarii

Este cunoscuta in practica sub numele de componenta ambientala. Pentru a nu calcula tot transportul luminii cu toate reflexiile de pe suprafete, se considera ca influenta indirecta a iluminarii este aceeasi in toate punctele din scena. Aceasta aproximare obtine rezultate satisfacatoare pentru o parte din scenarii.

Avem astfel:

ambient_component = Ka * global_ambient_color; # GLSL

  • Ka – constanta de reflexie ambientală a materialului
  • global_ambient_color – culoarea ambientală a luminii

Componenta difuză

In imaginea de mai jos se poate observa ca un fascicul de lumina ce are o latime de dimensiune A, este proiectat pe suprafata de-alungul unei zone de dimensiune B. Se poate ca in situatia in care fasciculul este proiectat vertical pe suprafata, B = A.

Notam cu alpha unghiul dintre vectorul spre directia sursei de lumina, L, si vectorul normal, N. Deoarece unghiul facut cu normala este 90 de grade, unghiul fata de vectorul L, realizat cu suprafata este de 90-alpha. Pentru ca suma unghiurilor unui triunghi este de 180 si triunghiul este dreptunghic, rezulta ca cel de-al treilea unghi din triunghi are dimensiunea alpha. Astfel, rezulta:

$$ cos(\alpha)=\frac{A}{B} \\ B=\frac{A}{cos(\alpha)} $$

Din acest motiv, se poate deduce ca intensitatea de iluminare pentru orice punct de pe suprafata este cos(alpha). In situatia in care alpha este 0 grade, intensitatea de iluminare este cos(0) = 1. Aceasta abordare poarta numele de legea cosinusului a lui Lambert, propusa de Johann Heinrich Lambert in 1760.

In grafica pe calculator, aceasta lege a cosinusului este utilizata pentru calculul de reflexie a uniforma in toate directiile. Mai exact, se considera ca lumina se imprastie uniform in toate directiile cu intensitatea de iluminare data de legea cosinusului a lui Lambert.

In practica, in loc de cosinus se utilizeaza produsul scalar dintre L si N, cu L si N, ambii de lungime 1. Interpretarea geometrica a produsului scalar este

$$ \vec{V_1}\cdot\vec{V_2}=\frac{cos(\angle(\vec{V_1},\vec{V_2}))}{\lVert\vec{V_1}\rVert\lVert\vec{V_2}\lVert} $$

In situatia in care vectorii V1 si V2 sunt de lungime 1 amandoi, expresia de mai sus este echivalenta cu:

$$ \vec{V_1}\cdot\vec{V_2}=cos(\angle(\vec{V_1},\vec{V_2})) $$

Pentru a obtine un vector unitate, de lungime 1, V' pe directia si in sensul dat de un vector V, putem aplica in limbajul glsl:

vec3 Vu = normalize(V);

Astfel, calculul componentei difuze a iluminarii este:

$$ componentaDifuza = K_d \cdot culoareLumina \cdot max(\vec{N}\cdot \vec{L}, 0) $$

In limbajul glsl, expresia de mai sus se transcrie sub forma:

vec3 diffuse_component = Kd * culoareLumina * max (dot(N,L), 0); # GLSL

  • Kd - constanta de reflexie difuză a materialului
  • culoareLumina – culoarea luminii
  • N – normala la suprafață (normalizată)
  • L – vectorul direcției luminii incidente (normalizat)
  • $max(\vec{N}\cdot \vec{L}, 0)$ – produsul scalar $\vec{N}\cdot \vec{L}$ reprezintă măsura unghiului dintre acești 2 vectori; astfel, dacă $i$ este mai mare decât $\pi/2$ valoarea produsului scalar va fi mai mică decât 0, acest lucru însemnând că suprafața nu primește lumină ( sursa de lumină se află în spatele suprafeței ) și de aici și formula care asigură că în acest caz suprafața nu primește lumină difuză

Componenta speculară

Pentru calcularea componentei speculare, vom folosi modelul propus de Bui Tuong Phong in 1973:

$$ componentaSpeculara = K_s \cdot culoareLumina \cdot primesteLumina \cdot (max(\vec{V}\cdot \vec{R}, 0))^n $$

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

  • Ks - constanta speculară de reflexie a materialului
  • V – vectorul direcției de vizualizare (normalizat)
  • R – vectorul direcției luminii reflectate (normalizat)
  • n – coeficientul de strălucire (shininess) al materialului
  • primesteLumina – 1 dacă $\vec{N}\cdot \vec{L}$ este mai mare decât 0; sau 0 în caz contrar

Componenta speculară reprezintă lumina reflectată de suprafața obiectului numai în jurul acestei direcții, $\vec{R}$. Acest vector se obține prin:

     vec3 R = reflect (-L, N) # GLSL

  • Este necesar să se utilizeze -L deoarece reflect() are primul parametru vectorul incident care intră în suprafață, nu cel care iese din ea așa cum este reprezentat în figură

În modelul Phong, se aproximează scăderea rapidă a intensității luminii reflectate atunci când $\alpha$ crește prin $(cos \alpha)^n$, unde $n$ este exponentul de reflexie speculară al materialului (shininess).

După cum se observă, față de celelalte 3 componente, componenta speculară depinde și de poziția observatorului. Dacă observatorul nu se află într-o poziție unde poate vedea razele reflectate, atunci nu va vedea reflexie speculară pentru zona respectivă. De asemenea, nu va vedea reflexie speculară dacă lumina se află în spatele suprafeței.

Atenuarea intensității iluminarii

Factorul de atenuare a intensitatii iluminarii pe baza de distanta se aplica doar componentelor difuza si speculara:

vec3 illumination = emissive_component + ambient_component
                    + attenuation_factor * ( diffuse_component + specular_component); # GLSL

  • attenuation_factor = $1/(d^2+1)$ este o funcție de atenuare
  • $d$ este distanța de la pozitia sursei de lumina la pozitia punctului de pe suprafață pentru care se calculeaza iluminarea

Surse de lumina de tip spot

Pentru a simula

Nu toate sursele de lumina sunt punctiforme. Daca dorim sa implementam iluminarea folosind o sursa de lumina de tip spot trebuie sa tinem cont de o serie de constrangeri

Asa cum se poate vedea si in poza pentru a implementa o sursa de lumina de tip spot avem nevoie de urmatorii parametri aditionali:

  • Directia de iluminare a sursei de lumina
  • Unghiul de taiere a iluminarii ce controleaza deschiderea conului de lumina
  • Un model de atenuare pe baza de unghi a intensitatii iluminarii ce tine cont valoarea de unghiului de taiere

Astfel, punctul P se afla in conul de lumina (primeste lumina) daca conditia urmatoare este indepilita:

float cos_theta_angle = dot(-L, light_direction);
float cos_phi_angle = cos(phi_angle);
 
if (cos_theta_angle > cos_phi_angle )
{
	// fragmentul este iluminat, astfel ca se calculeaza valoarea luminii conform modelului Phong
	// se calculeaza atenuarea luminii
}

Pentru a simula corect iluminarea de tip spot, este nevoie sa tratam si atenuarea luminii corespunzatoare apropierii unghiului de cut-off. Putem astfel sa utilizam un model de atenuare patratica ce ofera un rezultat convingator.

float cos_theta_angle = dot(-L, light_direction);
float cos_phi_angle = cos(phi_angle);
 
// Quadratic attenuation
float spot_linear_att_factor = (cos_theta_angle - cos_phi_angle) / (1.0f - cos_phi_angle);
float quadratic_spot_light_att_factor = pow(spot_linear_att_factor, 2);

Biblioteca GLM

Biblioteca GLM ne pune la dispozitie constructia de matrici pentru cele 3 tipuri de transformari analizate: translatie, modificare de scara si rotatie. Urmatoarele 2 lanturi de transformari sunt identice:

glm::mat4 model = glm::mat4(1);
model = glm::translate(model, glm::vec3(-5, 1.5f, 1));
model = glm::rotate(model, glm::radians(60.0f), glm::vec3(0, 1, 0));
model = glm::scale(model, glm::vec3(0.1f));
glm::mat4 model = glm::mat4(1);
model *= transform3D::Translate(glm::vec3(-5, 1.5f, 1));
model *= transform3D::RotateOY(glm::radians(60.0f));
model *= trasnform3D::Scale(glm::vec3(0.1f));

Detalii de implementare

  • Calculele de iluminare se vor face în spatiul lumii, deci înainte de a fi folosite, poziția și normala vor trebui aduse din spatiul obiectului în spatiul lumii. Aceste calcule se realizeaza in vertex shader si noua pozitie si vector normal se transmit spre fragment shader. Calculul se poate face astfel:
    • pentru poziție:
      vec3 world_position = (model_matrix * vec4(v_position,1)).xyz;
    • pentru normală:
      vec3 world_normal = normalize( mat3(model_matrix) * v_normal );
  • Vectorul normal N trebuie renormalizat in fragment shader, deoarece dupa procesul de interpolare, lungimea lui nu se pastreaza:
    vec3 N = normalize( world_normal );
  • Vectorul direcției luminii L:
    vec3 L = normalize( light_position - world_position );
  • Vectorul direcției din care priveste observatorul V:
    vec3 V = normalize( eye_position - world_position );

Funcții GLSL utile care pot fi folosite pentru implementarea modelului de iluminare

  • normalize(V) – normalizează vectorul V
  • normalize(V1+V2) – normalizează vectorul obținut prin V1+V2
  • normalize(P1-P2) - returnează un vector de direcție normalizat între punctele P1 și P2
  • dot(V1,V2) – calculează produsul scalar dintre V1 și V2
  • pow(a, shininess) – calculează a la puterea shininess
  • max(a,b) – returnează maximul dintre a și b
  • distance(P1,P2) – returnează distanța euclidiană dintre punctele P1 și P2
  • reflect(V,N) - calculează vectorul de reflexie pornind de la incidenta V și normala N

Cerinte laborator

Prin apasarea tastelor W, A, S, D, E si Q puteti controla pozitia unei surse de lumina. Prin apasarea tastei F puteti interschimba intre controlul a doua surse de lumina, una punctiforma si cealalta de tip spot.

  1. 0.05p - Trimiteti toate informatiile necesare calcularii iluminarii in atribute de tip uniform.
  2. 0.15p - Implementati calculul de iluminare in fisierele sursa ale programelor de tip shader:
    • Completati in fisierul VertexShader.glsl calculul pozitiei varfului si a vectorului normal in spatiul lumii si transmiteti-le spre fragment shader.
    • Completati in fisierul FragmentShader.glsl:
      • Calculul componentelor difuze si speculare ale iluminarii unei surse de lumina
      • Calculul factorului de atenuare a iluminarii pe baza de distanta
      • Calculul final de obtinere a iluminarii prin combinarea componentelor difuza si speculara, a factorului de atenuare si a culorii iluminarii
      • Calculul componentei ambientale a iluminarii globale
      • Până în acest punct, rezultatul pe care ar trebui să îl obțineti este următorul. Culoarea fiecarei lumini este aleasa aleator la inceputul fiecarei executii a aplicatiei grafice
  3. 0.05p - Implementati calculul de iluminare pentru sursele de lumina de tip spot:
    • Completati in fisierul FragmentShader.glsl:
      • Calculul factorului de atenuare specific unei surse de lumina de tip spot
      • Calculul final de obtinere a iluminarii prin combinarea componentelor difuza si speculara, a factorului de atenuare si a culorii iluminarii
  4. 0.05p - Pentru sursa de lumina de tip spot ce poate fi controlata de la tastatura, prin apasarea unor taste, modificati directia de iluminare si unghiul. Directia de vizualizare trebuie sa se poata roti fata de axa OX si OZ, in ambele sensuri, iar unghiul trebuie sa se poata mari si micsora.
ppbg/laboratoare/06.1700091502.txt.gz · Last modified: 2023/11/16 01:38 by andrei.lambru
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