This shows you the differences between two versions of the page.
egc:laboratoare:08 [2022/11/18 17:35] andrei.lambru |
egc:laboratoare:08 [2023/12/06 12:29] (current) anca.cristea [Iluminare Spot-light] |
||
---|---|---|---|
Line 2: | Line 2: | ||
**Video Laborator 8**: https://youtu.be/QuhUGAhrXUQ \\ | **Video Laborator 8**: https://youtu.be/QuhUGAhrXUQ \\ | ||
- | **Autori**: [[Ph.Dumitru@gmail.com | Philip Dumitru]], [[andrei.lapusteanu@upb.ro | Andrei Lăpușteanu]] | + | **Autori**: [[Ph.Dumitru@gmail.com | Philip Dumitru]], [[andrei.lapusteanu@upb.ro | Andrei Lăpușteanu]], [[caragicu_r@outlook.com | Robert Caragicu]] |
- | <hidden> | ||
==== Modelarea reflexiei luminii ==== | ==== Modelarea reflexiei luminii ==== | ||
Line 34: | Line 34: | ||
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. | ||
- | </hidden> | + | |
==== Iluminare Phong in Fragment Shader ==== | ==== Iluminare Phong in Fragment Shader ==== | ||
Line 109: | 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 121: | 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); | ||
Line 131: | Line 131: | ||
</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 147: | 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 153: | 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> |