Differences

This shows you the differences between two versions of the page.

Link to this comparison view

egc:laboratoare:08 [2020/11/24 13:35]
maria_anca.balutoiu [Cerinte laborator]
egc:laboratoare:08 [2023/12/06 12:29] (current)
anca.cristea [Iluminare Spot-light]
Line 1: Line 1:
 ====== Laboratorul 08 ====== ====== Laboratorul 08 ======
 +
 +**Video Laborator 8**: https://​youtu.be/​QuhUGAhrXUQ \\
 +**Autori**: [[Ph.Dumitru@gmail.com | Philip Dumitru]], [[andrei.lapusteanu@upb.ro | Andrei Lăpușteanu]],​ [[caragicu_r@outlook.com | Robert Caragicu]]
  
  
Line 26: Line 29:
   * am considerat că intensitatea sursei de lumină este o constantă float (cu valoarea 1)   * am considerat că intensitatea sursei de lumină este o constantă float (cu valoarea 1)
   * am ignorat culoarea emisă   * am ignorat culoarea emisă
-  * am înlocuit constanta de material $K_e$ cu constanta $K_d$ (pentru a trimite mai putine uniforme)+  * am înlocuit constanta de material $K_a$ cu constanta $K_d$ (pentru a trimite mai putine uniforme)
   * am considerat intensitatea luminii ambientale o constantă float (cu valoarea 0.25)   * am considerat intensitatea luminii ambientale o constantă float (cu valoarea 0.25)
  
 Totuși, trebuie să menționăm că modelul complet urmărește formula de mai sus, unde constantele de material $K_e, K_a, K_d, K_s$ sunt diferite și au 3 canale $(R,G,B)$, iar intensitatea luminii ambientale și intensitatea sursei de lumină au de asemenea 3 canale. Expresia luminii se evaluează separat pentru cele trei canale. Totuși, trebuie să menționăm că modelul complet urmărește formula de mai sus, unde constantele de material $K_e, K_a, K_d, K_s$ sunt diferite și au 3 canale $(R,G,B)$, iar intensitatea luminii ambientale și intensitatea sursei de lumină au de asemenea 3 canale. Expresia luminii se evaluează separat pentru cele trei canale.
 +
 +
  
 ==== Iluminare Phong in Fragment Shader ==== ==== Iluminare Phong in Fragment Shader ====
  
-Modeulul ​de iluminare aplicat in cazul implementarii in fragment shader este acelasi cu cel studiat in [[egc::​laboratoare::​07]].+Modelul ​de iluminare aplicat in cazul implementarii in fragment shader este acelasi cu cel studiat in [[egc::​laboratoare::​07]], din punct de vedere matematic.
 Totusi, exista o diferenta majora intre cele doua implementari prin faptul ca iluminarea nu se mai aplica la nivelul fiecarul vertex ci la nivel de fragment. Rezultatul final este superior calitativ intrucat iluminarea fiecarui fragment nu se va mai calcula pe baza interpolarii luminii calculate la nivel de vertex ci pe baza normalei si pozitiei in spatiu a fiecarui fragment. Totusi, exista o diferenta majora intre cele doua implementari prin faptul ca iluminarea nu se mai aplica la nivelul fiecarul vertex ci la nivel de fragment. Rezultatul final este superior calitativ intrucat iluminarea fiecarui fragment nu se va mai calcula pe baza interpolarii luminii calculate la nivel de vertex ci pe baza normalei si pozitiei in spatiu a fiecarui fragment.
  
-Valorile de intrare primite de Fragment Shader ​sunt interpolate linar intre valorile vertexilor ce compun primitiva utilizata la desenare.+Valorile de intrare primite de fragment shader ​sunt interpolate linar intre valorile vertexilor ce compun primitiva utilizata la desenare.
  
 {{ :​egc:​laboratoare:​light:​rgb-trianglej.jpg?​direct |}} {{ :​egc:​laboratoare:​light:​rgb-trianglej.jpg?​direct |}}
Line 104: Line 109:
 Astfel, punctul **P** se afla in conul de lumina (primeste lumina) daca conditia urmatoare este indepilita: Astfel, punctul **P** se afla in conul de lumina (primeste lumina) daca conditia urmatoare este indepilita:
 <code glsl> <code glsl>
-float cut_off = radians(30);​+float cut_off = radians(30.0f);
 float spot_light = dot(-L, light_direction);​ float spot_light = dot(-L, light_direction);​
 if (spot_light > cos(cut_off)) if (spot_light > cos(cut_off))
Line 116: Line 121:
  
 <code glsl> <code glsl>
-float cut_off = radians(30);​+float cut_off = radians(30.0f);
 float spot_light = dot(-L, light_direction);​ float spot_light = dot(-L, light_direction);​
 float spot_light_limit = cos(cut_off);​ float spot_light_limit = cos(cut_off);​
  
 // Quadratic attenuation // Quadratic attenuation
-float linear_att = (spot_light - spot_light_limit) / (1 - spot_light_limit);​+float linear_att = (spot_light - spot_light_limit) / (1.0f - spot_light_limit);​
 float light_att_factor = pow(linear_att,​ 2); float light_att_factor = pow(linear_att,​ 2);
  
 </​code>​ </​code>​
  
 +
 +==== Iluminarea suprafețelor folosind mai multe lumini ====
 +
 +Pentru a simula mai multe lumini, putem scrie un shader care să calculeze contribuția fiecărei lumini în parte. Pentru a fi ușor să scriem codul de shadere, acesta poate fi modularizat.
 +
 +În GLSL se pot defini funcții similar ca în limbajul C. Putem scrie o funcție pentru a calcula pentru o sursă de lumină culoarea rezultată din componentele difuze și speculare.
 +Un exemplu de funcție ar fi:
 +<code glsl>
 +vec3 point_light_contribution(vec3 light_pos, vec3 light_color)
 +{
 + vec3 color;
 + //​calculele componentelor difuze si speculare din modelul Phong de iluminare pentru lumina punctiforma.
 + return color;
 +}
 +</​code>​
 +
 +Putem accesa orice variabilă globală din orice funcție din cod, inclusiv uniforme. Astfel putem citi în funcția ''​point_light_contribution''​ normala suprafeței primită ca variabilă de intrare la fragment shader și uniformele cu constante de material, fără să le trimitem ca parametri.
 +
 +Putem specifica ce tip de parametrii are funcția:
 +  * ''​in''​ înseamnă că valoarea va fi copiată când se apelează funcția. Funcția poate modifica parametrul cum dorește
 +  * ''​out''​ înseamnă că valoarea nu fi inițializată de apelant și după ce funcția modifică parametrul valoarea va fi copiată în variabila corespunzătoare apelantului
 +  * ''​inout''​ le combină pe cele două
 +Cuvintele cheie ''​in'',​ ''​out''​ si ''​inout''​ se scriu înainte de tipul de data al parametrului funcției.
 +De exemplu, dacă dorim separat contribuția difuză și cea speculară, un exemplu de semnatură de funcție ar fi:
 +<code glsl>
 +void point_light_contribution(vec3 light_pos, vec3 light_color,​ out vec3 diffuse_contribution,​ out vec3 specular_contribution);​
 +</​code>​
 +
 +Dacă nu se specifică, parametrul este de tip ''​in''​. Astfel, putem construi funcții ce întorc mai multe valori.
 +
 +Metoda de declarare și definiție a funcțiilor este similară cu cea din C.
 +
 +<code glsl>
 +vec3 point_light_contribution(vec3 light_pos, vec3 light_color);​
 +
 +void main()
 +{
 + //...
 +}
 +
 +vec3 point_light_contribution(vec3 light_pos, vec3 light_color)
 +{
 + //...
 +}
 +</​code>​
 +
 +
 +**Nu este permisă recursivitate în GLSL.**
 +
 +
 +Pentru a trimite ușor multe surse de lumină, putem defini vectori de uniforme.
 +De exemplu, pentru a trimite mai multe surse de lumină punctiforme se declară în shader un vector de uniforme:
 +
 +<code glsl>
 +uniform vec3 point_light_pos[9];​
 +uniform vec3 point_light_color[9];​
 +</​code>​
 +
 +Pe urmă putem trimite uniformele cu un apel în cod:
 +
 +<code cpp>
 +glm::vec3 point_light_pos[9];​
 +glm::vec3 point_light_color[9];​
 +
 +GLuint location = glGetUniformLocation(program,​ "​point_light_pos"​);​
 +glUniform3fv(location,​ 9, glm::​value_ptr(point_light_pos[0]));​
 +//​glm::​value_ptr intoarce adresa de memorie unde se gasesc datele unui vector, matrici etc.
 +</​code>​
 +
 +O altă variantă este declararea unei structuri în shader
 +<code glsl>
 +struct light_source
 +{
 +   ​int ​ type;
 +   vec3 position;
 +   vec3 color;
 +   vec3 direction;
 +};
 +
 +uniform light_source lights[9];
 +</​code>​
 +
 +În GLSL structura este doar o definiție a unei agregări de tipuri de dată. Nu se poate obține locația unei structuri sau a unui vector de structuri. În schimb, putem interoga locația fiecărui membru din fiecare element din vectorul de structuri. De exemplu, se poate găsi locația uniformei ''​lights[0].position''​.
 +
 +Următorul cod C++ trimite pozițiile surselor de lumină în shader:
 +<code cpp>
 +light_source light_sources[9];​ //​light_source e o structura declarata similar cu cea scrisa in shader.
 +for (int i = 0;i < 9;++i)
 +{
 +    std::string name = std::​string("​lights["​) + std::​to_string(i) + std::​string("​].position"​);​
 +    GLuint location = glGetUniformLocation(program,​ name.c_str());​
 +    glUniform3fv(location,​ 1, glm::​value_ptr(light_sources[i].position));​
 +}
 +</​code>​
  
 ==== Cerinte laborator ==== ==== Cerinte laborator ====
Line 142: Line 241:
     * Directia de ilumiare este transmisa ca ''​uniform vec3 light_direction''​     * Directia de ilumiare este transmisa ca ''​uniform vec3 light_direction''​
     * Nu uitati sa aplicati un model de atenuare al luminii in functie de apropierea fragmentelor de unghiul de cut-off     * Nu uitati sa aplicati un model de atenuare al luminii in functie de apropierea fragmentelor de unghiul de cut-off
 +  - Sa se adauge în scenă o nouă sursă de lumină si sa se calculeze iluminarea
  
 **[Bonus]** **[Bonus]**
Line 148: Line 248:
     * rotirea spotului: **sus, jos, stanga, dreapta**     * rotirea spotului: **sus, jos, stanga, dreapta**
     * 2 taste pentru a creste/​micsora unghiul de iluminare al spot-ului     * 2 taste pentru a creste/​micsora unghiul de iluminare al spot-ului
 +
  
 <​hidden>​ <​hidden>​
----- +  ​- Modelul de iluminare Phong, folosind 3 canale de culoare:
-2. Modelul de iluminare Phong, folosind 3 canale de culoare:+
  
 Atât în implementearea laboratorului de săptămâna trecută, cât și în implementarea laboratorului din această săptămână,​ am folosit un model simplificat. Din acest motiv, propunem ca bonus să modificați fragment shader și vertex shader astfel încât să vedeți cum se face de fapt implementarea iluminării. Astfel, va trebui sa implementați următoarele:​ Atât în implementearea laboratorului de săptămâna trecută, cât și în implementarea laboratorului din această săptămână,​ am folosit un model simplificat. Din acest motiv, propunem ca bonus să modificați fragment shader și vertex shader astfel încât să vedeți cum se face de fapt implementarea iluminării. Astfel, va trebui sa implementați următoarele:​
   * Constantele de material Ke, Ka, Kd, Ks vor fi variabile de tip vec3, cu valori diferite pe toate cele cele 3 canale de culoare (de data aceasta va fi nevoie să trimiteți toate aceste constante către shader).   * Constantele de material Ke, Ka, Kd, Ks vor fi variabile de tip vec3, cu valori diferite pe toate cele cele 3 canale de culoare (de data aceasta va fi nevoie să trimiteți toate aceste constante către shader).
   * Veți renunța la variabila object_color prin care ați modelat culoarea obiectului. În această implementare,​ culoarea obiectului va fi calculată folosind cele 4 constante de material.   * Veți renunța la variabila object_color prin care ați modelat culoarea obiectului. În această implementare,​ culoarea obiectului va fi calculată folosind cele 4 constante de material.
-  * Intensitatea ​luminii ​și intensitatea luminii ambientale vor fi tot variabile de tip vec3, care poate avea și alte valori, nu numai glm::​vec3(1,​ 1, 1). Cei doi vectori ​de culoare ​pot fi diferiți. :-)+  * Intensitatea ​sursei de lumină ​și intensitatea luminii ambientale vor fi tot variabile de tip vec3, care pot avea și alte valori, nu numai glm::​vec3(1,​ 1, 1). Cei doi vectori pot fi diferiți. :-)
  
 Exemplu de rezultat (a se observa cum componenta difuză a luminii este mult mai roșiatică față de componenta speculară):​ Exemplu de rezultat (a se observa cum componenta difuză a luminii este mult mai roșiatică față de componenta speculară):​
Line 162: Line 262:
 {{ :​egc:​laboratoare:​phong.png?​500 |}} {{ :​egc:​laboratoare:​phong.png?​500 |}}
  
-</​hidden> ​ +</​hidden>​
  
egc/laboratoare/08.1606217741.txt.gz · Last modified: 2020/11/24 13:35 by maria_anca.balutoiu
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