Differences

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

Link to this comparison view

ppbg:laboratoare:10 [2023/12/21 12:27]
andrei.lambru [Cerințe laborator]
ppbg:laboratoare:10 [2024/12/03 15:19] (current)
andrei.lambru
Line 5: Line 5:
 </​note>​ </​note>​
  
-<​note ​tip+===== Programe de tip shader ​pentru ​prelucrarea geometriei =====
-Pentru rezolvarea cerințelor din cadrul acestui labroator:​ +
-  - [[https://​github.com/​UPB-Graphics/​gfx-framework-ppbg | Descărcați]] framwork-ul de laborator și copiați, din arhiva descărcată,​ directorul **Lab10**, în interiorul directorului //​gfx-framework-ppbg\src\lab//​ din versiunea voastră de proiect. +
-  - Adăugați în fișierul ''​lab_list.h'',​ linia ''#​include "​lab/​lab10/​lab10.h"''​. +
-  - 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 [[:​ppbg:​setup-framework | pagina]] dedicată acestui lucru. +
-</​note>​+
  
-===== Obiecte de tip framebuffer și umbre ===== +În acest laborator, ​se introduce ​un nou tip de program de tip shader ce are rolul de a prelucra geometria modelelor 3Dprecum triunghiurile dintr-rețea ​de triunghiuri prin care este definit un astfel ​de model. Acest tip de program ​de tip shader este cunoscut ​în limba engleză sub numele de **geometry shader** și are scopul de a oferi control asupra geometriei desenate. În banda grafică, el apare după pasul de asamblare a triunghiurilor,​ pe baza indicilor specificati în [[ https://ocw.cs.pub.ro/courses/ppbg/​laboratoare/​04#​index_buffer_object_ibo | IBO]]. O privire de ansamblu a benzii grafice, ce cuprinde și programele de tip geometry shader, poate fi vizualizată în imaginea de mai jos.
-  +
-În acest laborator, ​vom introduce ​atât elemente noi de OpenGLcât și abordare pentru calcularea umbrelor realizate ​de iluminarea unei surse de lumină ​de tip spot. Metoda prezentată aici se numeste //metoda mapării umbrelor//, întâlnită ​în limba engleză sub numele de //shadow mapping//.+
  
-Prima parte a laboratorului se concentrează doar pe descrierea obiectelor de tip framebuffer. Partea a doua descrie succint metoda mapării umbrelor și oferă mai multe detalii doar despre pașii tehnicii, ce țin de utilizarea obiectelor de tip framebuffer.+{{ :​ppbg:​laboratoare:​geometry-shader.png?600 |}}
  
-===== Obiecte ​de tip framebuffer =====+Pentru fiecare triunghi rezultat în urma procesului de asamblare pe baza indicilor din IBO, se apelează **o singură instanță** de program ​de tip geometry shader.
  
-Redarea scenei în fereastra de desenare se realizează,​ de fapt prin redarea scenei într-o textură specială, ce este afișată ulterior în fereastră. API-ul grafic OpenGL nu permite desenarea direct într-o textură, ci impune utilizarea unui obiect suplimentar,​ numit buffer de cadru sau framebuffer. Acest obiect conține: +====== Sintaxa limbajului GLSL ====== 
-  * **Texturile cu format ​de culoare în care se redă scena**. Pot să fie mai multe texturi pe care se desenează, până la un număr limită dat de procesorul grafic, care este în general 8. Putem să ne gândim la o textură ca la o structură de date în care păstrăm informație oarecare, nu doar culoare. De exempluputem păstra poziția în spațiul lume a fragmentului,​ obținută prin interpolare între vârfuri, sau vectorul normal în spațiul lume al fragmentului,​ obținut prin același proces de interpolare. +Un exemplu ​de vertex shader
-  * **Textura în care se păstrează informația de adâncime** a fragmentelor desenate în texturile cu format de culoare. Această informație este utilizată în pasul de test de adâncime din procesul de rasterizare.+<code glsl> 
 +#version 330 
 +  
 +layout(location = 0) in vec3 v_position;​ 
 +layout(location = 1) in vec2 v_texcoord;
  
-Câte un exemplu din informația celor două tipuri de texturi poate fi vizualizat mai jos. Mai exact, în prima imagine de mai jos se poate vedea informația dintr-o textură cu format de culoare, iar sub ea se poate vizualiza informația din textura cu format de adâncime obținută în urma desenării pe textura a cărei informații este vizibilă în prima imagine.+uniform mat4 Model; 
 +uniform mat4 View; 
 +uniform mat4 Projection;
  
-{{ :​ppbg:​laboratoare:​color_texture.png?​600 |}} +// coordonatele de textura ale varfului 
-{{ :​ppbg:​laboratoare:​depth_texture.png?​600 |}} +// atributele de iesire ale unui program de tip vertex shader 
-==== Crearea obiectelor ​de tip framebuffer ====+// sunt atribute de intrare pentru un program ​de tip geometry shader 
 +out vec2 vert_texcoord;​
  
-Pentru a crea un obiect de tip framebuffer,​ putem folosi directiva OpenGL: +void main() 
- +{ 
-<code cpp> +    ​gl_Position = Projection * View * Model * vec4(v_position1.0); 
-unsigned int framebuffer_object;​ +     
- +    vert_texcoord = v_texcoord;​ 
-glGenFramebuffers(1&​framebuffer_object);+}
 </​code>​ </​code>​
  
-Fereastra ​de desenare deține un framebuffer implicit, ce este creat automat în framework-ul de laborator prin intermediul bibliotecii GLFW. Astfel, orice redare a scenei se realizează inițial în texturile acestui framebuffer. Pentru a desena în texturile obiectului de tip framebuffer creat de noi mai sus sau pentru a modifica acest obiect, este necesară legarea acestuia la banda grafică după cum urmează:+Un exemplu ​de geometry shader: 
 +<code glsl> 
 +#version 330
  
-<code cpp> +// geometria primita la intrare este formata dintr-un triunghi 
-glBindFramebuffer(GL_FRAMEBUFFER,​ framebuffer_object); +layout(trianglesin;
-</​code>​+
  
-==== Crearea și atașarea texturilor ​la un framebuffer ====+// geometria transmisa ​la iesire 
 +layout(triangle_strip,​ max_vertices ​3) out;
  
-În momentul ​de față avem un framebuffer nou, gol, ce nu conține nicio textură ​de culoare sau de adâncime, dar care este legat la banda grafică. Putem lega texturi la framebuffer și atunci când vom reda o scenă și acest framebuffer va fi legat la banda grafică, procesul de desenare va scrie rezultatele în texturile obiectului legat de noi.+// atribut ​de intrare - coordonatele ​de textura ale varfurilor unui triunghi 
 +in vec2 vert_texcoord[3];​
  
-Reamintim că pentru a crea o textură cu format ​de culoare, folosim următoarele directive:+// atribut ​de iesire - coordonatele textura asociate fiecarui varf emis 
 +out vec2 geom_texcoord;​
  
-<code cpp> +void main() 
-unsigned int color_texture;+
 + gl_Position = gl_in[0].gl_Position;​ 
 + geom_texcoord = vert_texcoord[0];​ 
 + EmitVertex();
  
-glGenTextures(1, &​color_texture)+ gl_Position = gl_in[1].gl_Position;​ 
-glBindTexture(GL_TEXTURE_2D,​ color_texture);+ geom_texcoord = vert_texcoord[1]
 + EmitVertex();
  
-// Pixelii din interiorul texturii au formatul RGB + gl_Position = gl_in[2].gl_Position;​ 
-glTexImage2D(GL_TEXTURE_2D,​ 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE,​ NULL); + geom_texcoord = vert_texcoord[2];​ 
-</​code>​+ EmitVertex();
  
-Pentru a atașa textura cu format de culoare ​(R, RG, RGB, RGBA), creată mai sus, la framebuffer,​ folosim: + EndPrimitive(); 
- +        //​directiva aceasta incheie primitiva ​ 
-<code cpp> +}
-glFramebufferTexture(GL_FRAMEBUFFER,​ GL_COLOR_ATTACHMENT0+pct_atasare,​ color_texture,​ 0);+
 </​code>​ </​code>​
  
-Astfel, atașăm textura ''​color_texture''​ la obiectul ​de tip framebuffer legat la banda grafică pe punctul de atașare ''​pct_atasare''​. Valoarea ''​0'' ​de la final ne spune că atașăm primul nivel din mipmap (rezoluția maximă). Dupa cum se poate observa, obiectele de tip framebuffer au puncte de atașare ce sunt foarte similare din punct de vedere conceptual cu ideea de pipe, folosită la definirea informației la nivel de vertex. În API-ul grafic OpenGL, acest tip de proiectare este foarte des folosit. Dacă atașăm o textură la un punct de legare pe care deja este legată o altă textură, legătura veche se va pierde și va rămâne doar cea nouă.+==== Atribute ​de intrare ​șde iesire ====
  
-Este important ​să observăm mai sus că punctul de atașare este de tip ''​GL_COLOR_ATTACHMENT''​. Mai există un alt tip de punct de atașarecu un singur punct (unic!) folosit pentru textura de adâncimenumit ''​GL_DEPTH_ATTACHEMENT''​. ​Pentru a lega textură de adâncime, folosim:+  * Trebuie specificat tipul geometriei de la intrare: <code glsl> 
 +layout(triangles) in; 
 +</​code>​ Trebuie ​să fie unul dintre: ​''​points'', ​''​lines''​, ''​lines_adjacency'',​ ''​triangles'',​ ''​triangles_adjacency''​. ​Aceste tipuri de date sunt descrise într-secțiune următoare.
  
-<​code ​cpp+  * Trebuie specificat tipul geometriei de la ieșire: ​<​code ​glsl
-glFramebufferTexture(GL_FRAMEBUFFERGL_DEPTH_ATTACHMENT,​ depth_texture,​ 0); +layout(triangle_stripmax_vertices = 3out
-</​code>​+</​code> ​Trebuie să fie unul dintre: ''​points'',​ ''​line_strip'',​ ''​triangle_strip''​. Aceste tipuri de date sunt descrise într-o secțiune următoare.
  
-Procesul ​de creare a unei texturi ce conține informație ​de adâncime ​este similar cu cel de creare a unei texturi ce conține informație de culoare, descris mai sus, cu excepția formatului definit în directiva ​''​glTexImage2D''​: +  * Se primesc coordonatele ​de textură ​de la toată primitiva (triunghiul). Astfel că intrarea ​este un vector ​de 3 valori ​''​vec2''​. <code glsl> 
- +in vec2 vert_texcoord[3];​ 
-<​code ​cpp+</code>  
-glTexImage2D(GL_TEXTURE_2D0, GL_DEPTH_COMPONENT32F,​ width, height, 0, GL_DEPTH_COMPONENT,​ GL_UNSIGNED_BYTE,​ 0);+  * Nu este necesar să se dea dimensiunea vectorului. Astfelcodul de mai sus se poate scrie: <code glsl> 
 +in vec2 vert_texcoord[];
 </​code>​ </​code>​
  
-==== Specificarea texturilor de desenare ==== +  * De asemenea, există ​șun atribut implicit într-un program ​de tip geometry shader, cu numele ''​gl_in'', ​din care ne interesează ''​gl_Position''​: <​code ​glsl
- +in gl_PerVertex 
-Putem atașa mai multe texturi la un framebuffer,​ dar API-ul grafic OpenGL ne dă posibilitatea să alegem pe care vrem să le folosim la un pas de desenare. Putem să nu utilizăm unele din texturile unui framebuffer,​ chiar dacă ele sunt atașate la framebuffer. +{ 
- +  vec4 gl_Position
-Pentru a seta texturile ​care dorim să fie utilizate în procesul de desenare, folosim: +  ..
- +} gl_in[];
-<​code ​cpp+
-std::​vector<​GLenum>​ draw_textures;​ +
- +
-draw_textures.push_back(GL_COLOR_ATTACHMENT0+attachment_index_color_texture)+
- +
-glDrawBuffers(draw_textures.size(), &​draw_textures[0]);+
 </​code>​ </​code>​
  
-Pratic, cu directiva ''​glDrawBuffers'',​ setăm care sunt texturile în care se desenează. În exemplul ​de mai sus, avem o singură textură atașată pe atașamentul de culoare cu numărul 0, pe care o adaugăm într-un vector pe poziția 0.  Dacă avem obiectul ​de tip framebuffer în cauză legat la banda grafică și în fragment ​shader-ul utilizat pentru desenarea ​în acest framebuffer,​ avem codul de mai jos, deoarece în out_color scriem un pixel roșu, toți pixelii texturii de culoare vor fi roșii. +  * Atributele ​de ieșire ale unui program ​de tip geometry ​shader ​sunt descrise ​în secțiunea următoare: ​<code glsl> 
- +out vec2 geom_texcoord;
-<code glsl> +
-layout(location = 0) out vec4 out_color; +
- +
-void main() +
-+
-    out_color = vec4(1, 0, 0, 1); +
-}+
 </​code>​ </​code>​
  
-După cum s-a menționat mai sus, putem avea mai multe texturi cu format ​de culoare atașate unui framebuffer. Acest mecanism va fi prezentat în detaliu în laboratorul 6. Dar, ca o previzualizare a informației din acel laborator, codul de mai jos scrie în 4 texturi diferite, de tipuri diferite și se poate observa că textura din atașamentul de culoare numărul 0 este complet roșie, iar cea din atașamentul de culoare numărul 1 este complet albastră.+==== Emiterea ​de primitive ====
  
-<code glsl> +Pentru fiecare vârf emis dintr-un program de tip geometry shader, se poate asocia informație despre coordonata de textură, vectorul normal, culoarea și orice alt tip de informație asociată vârfului ​(specificate înainte de fiecare apel ''​EmitVertex()''​). 
-layout(location = 0) out vec4 out_color;​ +Acestea trebuie declarate ca variabile de ieșire. 
-layout(location = 1out vec3 color2; +După cum se poate observa, valoarea lui ''​geom_texcoord''​ este actualizată înainte de fiecare apel ''​EmitVertex()'':<​code glsl> 
-layout(location = 2out int int_texture;​ +gl_Position ​gl_in[0].gl_Position
-layout(location = 3) out float float_texture;​ +geom_texcoord ​vert_texcoord[0]
- +EmitVertex();
-void main() +
-+
-    out_color ​vec4(1, ​0, 0, 1)+
-    ​color2 ​vec3(0, 0, 1)+
-    ​int_texture = 1; +
-    float_texture = 3.14; +
-}+
 </​code>​ </​code>​
  
-În acest exemplupe atașamentul de culoare numărul 0 merge ce e scris în out_color, pe atașamentul ​de culoare cu numărul 1 merge ce este scris în color2, pe atașamentul de culoare cu numărul 2 merge ce este scris în int_texture,​ iar pe atașamentul de culoare cu numărul 3 merge ce este scris în float_texture.+Într-un geometry shaderse pot emite mai multe primitive (comanda ''​EmitVertex()''​ se poate da o dată sau de mai multe ori).
  
-==== Verificarea statusului creării unui framebuffer ​====+==== Tipuri de primitive ​====
  
-Ultima etapă necesară, înainte ​de folosirea obiectului ​de tip framebuffer, ​este testarea corectitudinii creării sale:+La ieșirea unui program de tip geometry shader, se permit doar 3 tipuri de date, cum a fost menționat mai sus: ''​points'',​ ''​line_strip''​ și ''​triangle_strip''​. Descrierea topologiei pentru fiecare tip de date este după cum urmează
 +  * ''​points'':​ se desenează un singur pixella poziția din poarta ​de afișare în care se regăsește fiecare vârf emis de un program ​de tip geometry shader. Un astfel de exemplu ​este reprezentat vizual în imaginea de mai jos. 
 +  * ''​line_strip'':​ se desenează linii între fiecare pereche consecutivă de vârfuri emise de un program de tip geometry shader. După cum se poate urmări în panoul din mijloc al imaginii de mai jos, pentru o listă de 6 vârfuri emise în ordinea { v0, v1, v2, v3, v4, v5 }, se creează o linie între vârfurile { v0, v1 }, { v1, v2 }, { v2, v3 }, { v3, v4 } și { v4, v5 }. 
 +  * ''​triangle_strip''​se desenează triunghiuri pentru toate tripletele consecutive de vârfuri emise de un program de tip geometry shader. După cum se poate urmări în panoul din dreapta al imaginii de mai jos, pentru o listă de 7 varfuri emise în ordinea { v0, v1, v2, v3, v4, v5, v6 }, se creează un triunghi cu vârfurile { v0, v1, v2 }, { v1, v2, v3 }, { v2, v3, v4 }, { v3, v4, v5 } și { v4, v5, v6 }.
  
-<code cpp> +{{ :​ppbg:​laboratoare:​triangles.png?​600 |}}
-glCheckFramebufferStatus(GL_FRAMEBUFFER);​ +
-</​code>​+
  
-==== Utilizarea obiectelor ​de tip framebuffer ====+La intrarea unui program ​de tip geometry shader se permit 5 tipuri de date, cum a fost menționat mai sus: ''​points'',​ ''​lines'',​ ''​lines_adjacency'',​ ''​triangles'',​ ''​triangles_adjacency''​. Pentru toate tipurile de date se primește exact **o singură instanță** din tipul de date specificat la execuția unei instanțe de program de tip geometry shader. Diferența principală între aceste tipuri de date este numărul de elemente primite în atributele de intrare ''​gl_in''​ și în atributele proprii programelor de tip shader. Mai exact: 
 +  * ''​points'':​ se primește exact //un singur// element în atributele de intrare. 
 +  * ''​lines'':​ se primesc //două// elemente în atributele de intrare. 
 +  * ''​lines_ajacency'':​ se primesc //4// elemente în atributele de intrare. 
 +  * ''​triangles'':​ se primesc //3// elemente în atributele de intrare. 
 +  * ''​triangles_adjacency'':​ se primesc //6// elemente în atributele de intrare.
  
-Așa cum s-a menționat mai sus, pentru redarea scenei în texturile unui obiect de tip framebuffer,​ este necesară legarea acestui obiect înainte ​de desenare:+===== Prelucrări la nivel de triunghi =====
  
-<code cpp> +Printre prelucrările frecvente asupra unui triunghise numără calcularea unui centru și a vectorului perpendicular pe planul triunghiului.
-glBindFramebuffer(GL_FRAMEBUFFERframebuffer_object);​ +
-</​code>​+
  
-În general, înainte de desenarea într-un framebuffer,​ vrem să curățăm texturile cu format de culoare și de adâncimeValoarea implicită de curățare este culoarea neagră pentru texturile cu format de culoare și valoarea ​pentru texturile cu format de adâncime:+Se poate calcula centroidul unui triunghi cu următoarea abordare: 
 +<code glsl> 
 +vec3 p1 = gl_in[0].gl_Position.xyz;​ 
 +vec3 p2 = gl_in[1].gl_Position.xyz;​ 
 +vec3 p3 = gl_in[2].gl_Position.xyz;​
  
-<code cpp> +vec3 center = (p1 + p2 + p3/ 3;
-glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);+
 </​code>​ </​code>​
  
-Trebuie specificată și poarta de vizualizare în care vrem să desenăm în texturile obiectului de tip framebuffer:+Se poate calcula vectorul perpendicular pe planul triunghiului cu abordarea: 
 +<code glsl> 
 +vec3 p1 = gl_in[0].gl_Position.xyz;​ 
 +vec3 p2 = gl_in[1].gl_Position.xyz;​ 
 +vec3 p3 = gl_in[2].gl_Position.xyz;​
  
-<code cpp> +vec3 v12 = normalize(p2 - p1); 
-glViewport(0, 0, width, height); +vec3 v13 = normalize(p3 - p1);
-</​code>​+
  
-În situația în care dorim sa desenăm în toată textura, width și height de mai sus reprezintă rezoluția texturilor din framebuffer. +// produs vectorial 
- +vec3 normal = cross(v12v13);
-În momentul în care se dorește din nou redarea scenei în texturile obiectului de tip framebuffer implicit, putem folosi: +
- +
-<code cpp> +
-glBindFramebuffer(GL_FRAMEBUFFER0);+
 </​code>​ </​code>​
  
-===== Metoda mapării umbrelor ​=====+===== Cerințe laborator ======
  
-Noi vom utiliza metoda mapării umbrelor ​pentru a obține ​efectul ​de umbre ale iluminării realizate ​de către sursă de lumină de tip spot.+  - 0.05p - Completați fișierele ''​LabShader.GS.glsl''​ și ''​Texture.FS.glsl''​ pentru a desena geometria arcașei pe baza texturii. După acest pas, rezultatul vizual ar trebui să fie urmatorul: {{ :​ppbg:​laboratoare:​geometry-shader1.png?​600 |}} 
 +  - 0.05p - Modificați programul de tip geometry shader din fișierul ''​LabShader.GS.glsl''​ pentru a desena obiectele pentru care se utilizează acest program de tip shader de cel puțin 5 ori, la poziții diferite în scenă. Desenările se pot realiza pe aceeași linie, la intervale regulate între ele. 
 +  - 0.1p - Completați fișierele ''​Triangle.GS.glsl''​ și ''​Color.FS.glsl'' ​pentru a obține ​următorul rezultat vizual: {{ :​ppbg:​laboratoare:​geometry-shader2.png?​600 |}} 
 +    * Utilizați programul ​de tip shader pentru desenarea triunghiului din centru. 
 +    * Pentru a obține rezultatul vizual din imagine, la ieșire trebuie transmise mai multe triunghiuri :) . 
 +  - 0.05p - Creați un alt program de tip geometry shader cu care să realizați o animație ​de "​explozie"​ a geometriei, similară cu cea din imaginea următoare: {{ :​ppbg:​laboratoare:​geometry-shader.gif?​600 |}} 
 +    * Aveți în vedere ​că animația de "​explozie"​ se resetează după un interval de timp. Hint: utilizați timpul aplicației și informația vectorilor normali. 
 +  - 0.05p - Creați un alt program de tip geometry shader cu care să desenați marcaje liniare ce specifică direcția vectorului normal în fiecare vârf al rețelei de triunghiuri ce formează geometria. 
 +    * Desenați de două ori geometria: odată se utilizează un program de tip shader care desenează triunghiurile peste care se aplică textura și a doua oară în care se utilizează un program ​de tip geometry shader cu care se desenează liniile ce reprezintă vectorii normali. 
 +    * Specificați tipul geometriei transmise la ieșire în programul ​de tip geometry shader la ''​line_strip''​. 
 +    * Trebuie desenată o linie pentru fiecare vârf, cu care se specifică direcția vectorului normal din informația vârfului.  
 +    * Rezultatul vizual ar trebui să fie similar cu cel din imaginea de mai jos: {{ :​ppbg:​laboratoare:​geometry-shader3.png?600 |}}
  
-Metoda conține 2 pași+Bonus: Creați un alt program ​de tip geometry shader cu care să realizațun efect de explozie ​în care geometria ​este afectată de gravitațiesimilar ​cu cea din imaginea de mai jos: 
-  - Redarea scenei într-un framebuffer nou. Această desenare se realizează din poziția sursei ​de lumină, pe direcția de iluminare a sursei, specifică tipului de sursă spot. Practic, dorim să vedem ceea ce "​vede"​ sursa de lumină. Pentru simplitate, în laboratorul acesta, sursa va avea un unghi de iluminare de 90 de grade, motiv pentru care se va folosi o proiecție perspectivă cu un unghi de vizualizare atât vertical cât și orizontal de 90 de grade. Texturile obiectului de tip framebuffer,​ obținute ​în urma desenării, **conțin toate punctele din scenă ce sunt iluminate de către sursa de lumină**. +{{ :​ppbg:​laboratoare:​geometry-shader1.gif?600 |}}
-  - Redarea scenei în texturile obiectului de tip framebuffer implicit din perspectiva observatorului. În această desenare, se folosește textura cu format de adâncime obținută la pasul anterior. În fragment shader, fiecare fragment se verifică daca este iluminat de către sursa de lumină sau nu. Dacă pozitia în spațiul lume a fragmentuluiobținută prin interpolare între vârfuri, "​apare"​ în texturile de culoare ale obiectului de tip framebuffer,​ obținut prin desenarea scenei de la pasul anterior, înseamnă că acel fragment este iluminat și trebuie să se calculeze intensitatea iluminării pentru acesta. Acest "​apare"​ este descris puțin mai în detaliu mai jos. +
- +
-==== Umbrirea unui fragment ==== +
- +
-Pentru a verifica dacă un fragment obținut prin redarea scenei din perspectiva observatorului este iluminat sau se află în umbră, putem folosi textura cu format de adâncime din obiectul de tip framebuffer obținut la pasul 1. Se verifică dacă distanța dintre poziția în spațiul lume a fragmentului este aceeași ​cu cea din textura cu format de adâncime de la pasul 1, când poziția fragmentului este proiectată în această textură. +
- +
-O exemplificare a acestui proces se regăsește în imaginea de mai jos, unde pixelul marcat cu roșu în panoul a) este proiectat în pixelul marcat cu roșu din textura cu formatul de adâncime, vizibilă în panoul b). Se poate observa că fragmentul marcat cu roșu în panoul a) a fost obținut prin rasterizarea modelului ce descrie terenul, dar proiecția lui pe textura de adâncime, întâlnește un pixel rezultat în urma rasterizării modelului de bambus. +
- +
-{{ :​ppbg:​laboratoare:​sm.png?700 |}} +
- +
-În situația în care distanța dintre poziția în spațiul lume a fragmentului pentru care se calculează iluminarea și sursa de lumină este mai mare decat cea din textura cu format de adâncime, înseamnă că în această textură este desenat un obiect ce se află mai aproape de sursa de lumină și astfel umbrește fragmentul pentru care calculăm intensitatea iluminării. Acest exemplu este chiar în imaginea de mai sus, unde poziția în spațiul lume a fragmentului din panoul a), de pe teren, este mai departe de sursa de lumină față de pixelul ce se regăsește la poziția proiecției lui în textura cu format de adâncime, unde se află un fragment din frunza bambusului. O observație importantă de care trebuie să se țină cont este ca cele două distanțe sa se compare în același spațiu. +
- +
-Trimiterea texturii cu format de adâncime se poate realiza la fel ca trimiterea unei texturi cu format de culoare. API-ul grafic OpenGL are și un alt mecanism special pentru aceste tipuri de texturi, nefolosit în acest laborator. Vedeți observația de mai jos. +
- +
-<code cpp> +
-glActiveTexture(GL_TEXTURE0+nr_unitate_texturare);​ +
-glBindTexture(GL_TEXTURE_2D,​ depth_texture);​ +
- +
-glUniform1i(glGetUniformLocation(shader->​program,​ "​depth_texture"​),​ nr_unitate_texturare);​ +
-</​code>​ +
-  +
-<note tip> +
-Există mai multe abordări de implementare a metodei de mapare a umbrelor. În laboratorul curent, există o implementare minimală a metodei, ce are scop didactic. Implementarea se regăsește deja aproape completă în framework, astfel că rămâne ca voi să vă concentrați pe gestionarea obiectelor de tip framebuffer. Dacă doriți să aflați mai multe informații despre abordările posibile pentru implementarea acestei metode, puteți consulta următoarele resurse: +
-  * LearnOpenGL - https://​learnopengl.com/​Advanced-Lighting/​Shadows/​Shadow-Mapping +
-  * Tipul de date //shadow samplers// - [[https://​www.khronos.org/​opengl/​wiki/​Sampler_(GLSL)#​Shadow_samplers]] +
-</​note>​+
  
-===== Cerințe laborator =====+Utilizați ecuația mișcării:
  
-  - 0.25p - Creați un obiect de tip framebuffer și utilizați-l pentru a desena geometria obiectelor din perspectiva sursei de lumină de tip spot: 
-    * Completați metoda ''​CreateFramebuffer()''​ pentru a genera un nou obiect de tip framebuffer,​ împreună cu texturile atașate la el. 
-    * Legați, pe rând, obiectul de tip framebuffer,​ creat anterior, la banda grafică pentru pasul 1 al metodei de mapare a umbrelor și obiectul de tip framebuffer implicit pentru pasul 2. După acest proces, dacă totul a fost realizat corect până aici, pe ecran se vor afișa în partea dreapta-jos,​ texturile cu format de culoare și de adâncime ale obiectului de tip framebuffer creat de voi, obținut prin redarea geometriei obiectelor din poziția sursei de lumină. Pentru a schimba între afișarea și ascunderea texturilor de pe ecran, se poate folosi tasta **F1**. 
-    * După acest pas, rezultatul pe care ar trebui să îl obțineti este următorul: {{ :​ppbg:​laboratoare:​shadows.png?​600 |}} 
-  - 0.05p - Utilizați textura cu format de adâncime obținută prin redarea geometriei obiectelor din perspectiva sursei de lumină pentru a crea efectul de umbre: 
-    * În metoda ''​RenderSimpleMesh'',​ trimiteți textura cu format de adâncime din obiectul de tip framebuffer creat de voi, obținută la pasul 1 al metodei de mapare a umbrelor. 
-    * Utilizați factorul de umbrire în programul de tip fragment shader cu numele ''​ShadowMappingPassTwo.FS.glsl''​. 
-    * După acest pas, rezultatul pe care ar trebui să îl obțineti este următorul: {{ :​ppbg:​laboratoare:​shadows1.png?​600 |}} 
  
-<note tip> +$$ 
-Poziția sursei de lumină de tip spot poate fi controlată prin intermediul tastelor **W**, **S**, **A**, **D**, **Q** și **E**, în absențapăsării butonului dreapta de la mouse. De asemenea, direcția de iluminare a sursei de lumină se poate controla prin săgeți. +P = P_0 + \vec{V} \cdot t + \frac{1}{2} \cdot \vec{a} \cdot t^2 
-</​note>​+$$
  
-BonusCompletați fișierul ''​ShadowMappingPassTwo.FS'' ​pentru ​a crea efectul de iluminare volumetrică. Rezultatul vizual ar trebui să fie similar cu cel din imaginea de mai jos: +unde V este o direcție de mișcare specifică fiecărui triunghi ​:), iar a este vec3(0, -1, 0). Puteți utiliza ​și alte valori ​pentru ​acceleratia gravitațională. t este timpul animației. Aveți în vedere că triunghiurile nu coboară sub valoarea 0 pentru componenta y. Animația se resetează după un anumit timp.
-{{ :​ppbg:​laboratoare:​volumetric-illumination.png?600 |}}+
ppbg/laboratoare/10.1703154420.txt.gz · Last modified: 2023/12/21 12:27 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