Differences

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

Link to this comparison view

ppbg:laboratoare:09 [2023/12/13 21:31]
andrei.lambru
ppbg:laboratoare:09 [2024/10/02 09:59] (current)
andrei.lambru
Line 5: Line 5:
 </​note>​ </​note>​
  
-<​note ​tip> +===== Obiecte de tip framebuffer și umbre ===== 
-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 **Lab9**, în interiorul directorului ​//gfx-framework-ppbg\src\lab// din versiunea voastră de proiect. +În acest laborator, vom introduce atât elemente noi de OpenGL, cât și o 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//.
-  - Adăugați în fișierul ''​lab_list.h'',​ linia ''#​include "lab/lab9/lab9.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>​+
  
-===== Curbe de forma libera =====+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.
  
-Introducem conceptul ​de curba de forma libera pentru acele curbe ce nu pot fi definite analitic, printr-o formula inchisa. Exemple de curbe analitice sunt: +===== Obiecte ​de tip framebuffer =====
-  * Cercul -   $ F_c(t) ​(c + r \cdot cos(t), c + r \cdot sin(t)) $   +
-  * Elipsa -  $ F_e(t) ​(c + r_1 \cdot cos(t), c + r_2 \cdot sin(t)) $   +
-  * ... +
  
-Orice curba ce poate fi desenata intr-un planindiferent cat de neregulata ​este forma, se considera curba de forma liberaAceasta clasa de curbe include si curbele analitice.+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: 
 +  * **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 oarecarenu doar culoare. De exemplu: putem 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. 
 +  * **Textura în care se păstrează informația ​de adâncime** a fragmentelor desenate în texturile cu format de culoareAceastă informație este utilizată în pasul de test de adâncime din procesul ​de rasterizare.
  
-===== Curbe Bézier =====+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.
  
-Prima curba de forma libera ce a fost definita, cronologic, este curba de baza descrisa mai jos ce a fost popularizata de catre Pierre Bézier in anii 60'Aceasta este descrisa initial ​de catre Paul de Casteljau in obtinerea unui patent in 1959, dar este publicata abia in anii 80'. Cei doi autori au dezvoltat parametrizarea acestei forme independent.+{{ :​ppbg:​laboratoare:​color_texture.png?600 |}} 
 +{{ :​ppbg:​laboratoare:​depth_texture.png?​600 |}} 
 +==== Crearea obiectelor ​de tip framebuffer ====
  
-Curba Bézier este o curba de aproximare ce contine ​un set de puncte ce controleaza forma curbei. Acest set poate contine orice numar de puncte. Formula pentru 23 si 4 puncte de control arata in felul urmator:+Pentru a crea un obiect ​de tip framebufferputem folosi directiva OpenGL:
  
-^ Nr. \\ puncte \\ control ^ Formula ^ Reprezentare vizuala statica ^ Reprezentare vizuala animata | +<code cpp> 
-| 2 |  $ B_2(P_0, P_1, t) = (1-t) \cdot P_0 + t \cdot P_1 $  | {{ :​ppbg:​laboratoare:​bézier_1.png?​400 |}} | {{ :​ppbg:​laboratoare:​bézier_1_big.gif?​400 |}} | +unsigned int framebuffer_object;​
-| 3 |  $ B_3(P_0, P_1, P_2, t) = (1-t) \cdot B_2(P_0, P_1, t) + t \cdot B_2(P_1, P_2, t) $  |{{ :​ppbg:​laboratoare:​bézier_2.png?​400 |}} |  {{ :​ppbg:​laboratoare:​bézier_2_big.gif?​400 |}} | +
-| 4 |  $ B_4(P_0, P_1, P_2, P_3, t) = (1-t) \cdot B_3(P_0, P_1, P_2, t) + t \cdot B_3(P_1, P_2, P_3, t) $  |{{ :​ppbg:​laboratoare:​bézier_3.png?​400 |}} |  {{ :​ppbg:​laboratoare:​bézier_3_big.gif?​400 |}} |+
  
-==== Definitie recursiva ====+glGenFramebuffers(1,​ &​framebuffer_object);​ 
 +</​code>​
  
-Formula curbei Bézier ​se poate defini recursiv dupa cum urmeaza:+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ă:
  
 +<code cpp>
 +glBindFramebuffer(GL_FRAMEBUFFER,​ framebuffer_object);​
 +</​code>​
  
 +==== Crearea și atașarea texturilor la un framebuffer ====
  
-$$ +În momentul de față avem un framebuffer nougolce nu conține nicio textură de culoare sau de adâncimedar 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.
-B_{n}(P_0P_1,..., P_n, t) = (1-t) \cdot B_{n-1}(P_0,​ P_1,..., P_{n-1}, t) + t \cdot B_{n-1}(P_1,​ P_2,..., P_{n}, t) +
-$$+
  
 +Reamintim că pentru a crea o textură cu format de culoare, folosim următoarele directive:
  
-==== Forma polinomiala ====+<code cpp> 
 +unsigned int color_texture;​
  
-Forma polinomiala a curbei Bézier este dupa cum urmeaza:+glGenTextures(1,​ &​color_texture);​ 
 +glBindTexture(GL_TEXTURE_2D,​ color_texture);​
  
 +// Pixelii din interiorul texturii au formatul RGB
 +glTexImage2D(GL_TEXTURE_2D,​ 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE,​ NULL);
 +</​code>​
  
-$$ +Pentru a atașa textura cu format de culoare ​(R, RG, RGB, RGBA), creată mai sus, la framebuffer,​ folosim:
-B(t= \sum_{i=0}^{n}{\binom{n}{i} \cdot (1-t)^{n-i} \cdot t^i \cdot P_i}\quad 0 \leq t \leq 1 +
-$$+
  
-Pentru 4 puncte de controlforma curbei Bézierpe baza definitiei de mai susarata in felul urmator:+<code cpp> 
 +glFramebufferTexture(GL_FRAMEBUFFERGL_COLOR_ATTACHMENT0+pct_atasarecolor_texture0); 
 +</​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ă.
  
 +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șare, cu un singur punct (unic!) folosit pentru textura de adâncime, numit ''​GL_DEPTH_ATTACHEMENT''​. Pentru a lega o textură de adâncime, folosim:
  
-$$ +<code cpp> 
-B(t) = (1-t)^3 \cdot P_0 + 3(1-t)^2 \cdot t \cdot P_1 + 3(1-t)^2 \cdot P_2 + t^3 \cdot P_3\quad \leq t \leq 1 +glFramebufferTexture(GL_FRAMEBUFFER,​ GL_DEPTH_ATTACHMENT,​ depth_texture, 0); 
-$$+</​code>​
  
 +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'':​
  
-Polinomul urmatorutilizat in definirea formei polinomiale a curbei Béziereste cunoscut sub numele de polinom Bernsteindupa numele lui Sergei Bernsteince l-a propus in anul 1912:+<code cpp> 
 +glTexImage2D(GL_TEXTURE_2D0GL_DEPTH_COMPONENT32Fwidthheight, 0, GL_DEPTH_COMPONENT,​ GL_UNSIGNED_BYTE,​ 0); 
 +</​code>​
  
-$$ +==== Specificarea texturilor de desenare ====
-b_{i,​n}(t) ​\binom{n}{i} \cdot t^i \cdot (1-t)^{n-i},​ \quad i=0,...,n +
-$$+
  
 +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.
  
-===== Suprafete generate =====+Pentru a seta texturile care dorim să fie utilizate în procesul de desenare, folosim:
  
-Definim o suprafata generata sub forma unei suprafete create printr-o metoda de multiplicare a unei geometrii suport. Procesul de creare a unei astfel de suprafete necesita: +<code cpp> 
-  * O geometrie generator, ce este definită explicit si pe baza căreia are loc procesul de generare. +std::​vector<​GLenum>​ draw_textures;​
-  * Un algoritm de generare. Acesta poate fi bazat pe replicare urmata de un proces de translație,​ rotație sau orice alt proces pe baza unei reguli ad-hoc.+
  
-Procesul de generare decurge astfel: întâi se desenează geometria generator, pe baza căreia este construită suprafața generată. După aceasta, se desenează un număr de instanțe ale geometriei generator, fiecare transformată de funcția de generare într-un mod progresiv. Rezultatul final este obținut prin combinarea topologică a acestor instanțe.+draw_textures.push_back(GL_COLOR_ATTACHMENT0+attachment_index_color_texture);​
  
-==== Suprafețe de translație ====+glDrawBuffers(draw_textures.size(),​ &​draw_textures[0]);​ 
 +</​code>​
  
-O suprafață de translație este suprafață generată prin instanțierea unui obiect generator. Fiecare instanță a generatorului suferă o transformare de translațieO suprafață de translație poate fi definită prin instanțierea unui generator cu fiecare instanță translatată progresiv dupa o funcție.+Pratic, cu directiva ''​glDrawBuffers'',​ setăm care sunt texturile în care se desenează. În exemplul ​de mai sus, avem singură textură atașată pe atașamentul de culoare cu numărul 0, pe care 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.
  
-Un exemplu de suprafață translatată este:+<code glsl> 
 +layout(location = 0) out vec4 out_color;
  
-{{ :​ppbg:​laboratoare:​translation-surface.png?​600 |}}+void main() 
 +{ 
 +    out_color = vec4(1, 0, 0, 1); 
 +} 
 +</​code>​
  
-==== Suprafețde rotație ====+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ă.
  
-O suprafață de rotație este o suprafață generată prin instanțierea unui obiect generator. Fiecare instanță a generatorului suferă o transformare de rotație. Aceasta poate fi definită prin instanțierea unui generator cu fiecare instanță rotită progresiv dupa o funcție.+<code glsl> 
 +layout(location = 0) out vec4 out_color;​ 
 +layout(location = 1) out vec3 color2; 
 +layout(location = 2) out int int_texture;​ 
 +layout(location = 3) out float float_texture;​
  
-{{ :​ppbg:​laboratoare:​rotation-surface.png?600 |}}+void main() 
 +{ 
 +    out_color = vec4(1, 0, 0, 1); 
 +    color2 = vec3(0, 0, 1); 
 +    int_texture = 1; 
 +    float_texture = 3.14; 
 +} 
 +</​code>​
  
-===== Laborator =====+În acest exemplu, pe 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.
  
 +==== Verificarea statusului creării unui framebuffer ====
  
-Instanțierea reprezintă un mecanism prin care se amplifică numărul ​de primitive trimise la banda grafică. Această amplificare este fie explicită (programată ​de utilizator în shader)fie implicită (generată prin comenzi OpenGL).+Ultima etapă necesară, înainte ​de folosirea obiectului ​de tip framebuffereste testarea corectitudinii creării sale:
  
-Pentru ​instanția implict geometrieexistă comanda:+<code cpp> 
 +glCheckFramebufferStatus(GL_FRAMEBUFFER);​ 
 +</​code>​ 
 + 
 +==== Utilizarea obiectelor de tip framebuffer ==== 
 + 
 +cum s-a menționat mai sus, pentru redarea scenei în texturile unui obiect de tip framebuffereste necesară legarea acestui obiect înainte de desenare:
  
 <code cpp> <code cpp>
-glDrawElementsInstanced(topologienr_indecsi, tip_data, offset, instante).+glBindFramebuffer(GL_FRAMEBUFFERframebuffer_object);
 </​code>​ </​code>​
  
-De exempludacă se doreste ​desenarea de 1540 de ori (instanțe) ale unui obiect ​cu 99 de indici, ​format ​din triunghiuri din buffer-ul ​de indici, legat curent la banda grafică, atunci comanda ar fi:+În generalînainte de desenarea ​într-un framebuffer,​ vrem să curățăm texturile cu format ​de culoare și de adâncime. Valoarea implicită de curățare este culoarea neagră pentru texturile ​cu format ​de culoare și valoarea 1 pentru texturile cu format de adâncime:
  
 <code cpp> <code cpp>
-glDrawElementsInstanced(GL_TRIANGLES,​ 99, GL_UNSIGNED_INT,​ 0, 1540);+glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 </​code>​ </​code>​
  
-Instanțierea explicită se face în shader, generând geometrie nouă prin comenzi glsl, în acest caz prin comenzi ​de geometry shader: +Trebuie specificată și poarta de vizualizare ​în care vrem să desenăm ​în texturile obiectului ​de tip framebuffer:
-<code glsl> +
-for (int i=0;​i<​10;​i++) { +
-    gl_Position = P*V*M*vec4(p1,​ 1);​ EmitVertex();​ +
-    gl_Position = P*V*M*vec4(p2,​ 1);​ EmitVertex();​ +
-    gl_Position = P*V*M*vec4(p3,​ 1);​ EmitVertex();​ +
-EndPrimitive();​+
  
-}+<code cpp> 
 +glViewport(0,​ 0, width, height);
 </​code>​ </​code>​
  
-In situatia in care se utilizeaza instantiere implicitain programul ​de tip vertex shader, se poate obtine numarul de ordine al instantei ​din care face parte varful procesat, prin utilizarea atributului de intrare implicit ''​gl_InstanceID''​.+În situația în care dorim sa desenăm în toată texturawidth și height ​de mai sus reprezintă rezoluția texturilor ​din framebuffer.
  
-Instanțirea oferă posibilitatea ușoară de a crește rapid numărul ​de obiecte din scenădacă obiectele sunt identice. Excopaci, tile-uri de teren, unități într-un rts, etc.+În momentul în care se dorește din nou redarea scenei în texturile obiectului ​de tip framebuffer implicitputem folosi:
  
-Pentru a lucra cu suprafețe de translațierotație și/sau interpolare,​ se utilizeaza instanțiere. Totuși, chiar dacă avem N instanțe de geometrie generator, nu avem topologia necesară pentru a lega instanțele,​ deoarece generatorul este o curbă (topologie 2D), iar suprafața generată necesită topologie 3D.+<code cpp> 
 +glBindFramebuffer(GL_FRAMEBUFFER0); 
 +</code>
  
-{{ :​spg:​laboratoare:​poza_suprafete.png?​600 |}}+===== Metoda mapării umbrelor =====
  
-Din figură se observă clar cum avem mai multe tipuri de obiecte: +Noi vom utiliza metoda mapării umbrelor pentru a obține efectul de umbre ale iluminării realizate ​de către o sursă de lumină de tip spot.
-  - Obiectul generator (prima linie neagră din stânga) +
-  - Obiectul nou generat (2 instanțale generatorului și topologie ​de legatură între linii) +
-  - Suprafața finală generată+
  
-Dacă nu am fi folosit acest procesatunci prin instanțiere am fi obținut liniile instanțiatedar nu și topologia ​de legatură între liniiadică exact ca în următoarea imagine:+Metoda conține 2 pași: 
 +  - 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ă**. 
 +  - Redarea scenei în texturile obiectului de tip framebuffer implicit din perspectiva observatorului. În această desenarese folosește textura cu format ​de adâncime obținută la pasul anterior. În fragment shaderfiecare fragment se verifică daca este iluminat de către sursa de lumină sau nu. Dacă pozitia ​în spațiul lume a fragmentului,​ obț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.
  
-{{ :​spg:​laboratoare:​poza_curbe.png?​300 |}}+==== Umbrirea unui fragment ====
  
-===== Cerinte laborator =====+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ă.
  
-  - 0.1p - Modificati fisierul ''​GeometryShader.glsl''​ pentru ​desena o curba Bézier pe baza 4 puncte ​de control+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 ​afost 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
-    * Utilizati formula specifica unei curbe Bézier ​cu 4 puncte ​de controldescrisa ​mai sus. + 
-    * Desenati o banda de linii, pe baza tipului ​de geometrie ​de iesire ''​line_strip''​prin emiterea mai multor varfuri ale caror pozitii ​se obtin prin esantionarea curbei Bézier+{{ :​ppbg:​laboratoare:​sm.png?​700 |}} 
-    * Permiteti modificarea ​de la tastatura a numarului ​de varfuri ce desriu banda de liniiAcest numar trebuie sa poata fi scazut si crescut+ 
-    * Dupa acest pasrezultatul ​pe care ar trebui sa il obtineti este urmatorul:  +Î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ăriiAcest exemplu este chiar în imaginea ​de mai susunde 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âncimeunde 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
-{{ :ppbg:laboratoare:​bezier-animation.gif?600 |}} + 
-  - 0.15p Modificati fisierul ''​GeometryShader.glsl'' ​pentru a desena ​o suprafata ​de translatie, pe baza curbei Bézier obtinute anterior. +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 laboratorVedeți observația de mai jos
-    * Desenati o banda de triunghiuri,​ pe baza tipului de geometrie de iesire ​''​triangle_strip''​, prin emiterea mai multor varfuri ale caror pozitii se obtin prin esantionarea ​doua curbe Bézieralaturate+ 
-    * Utilizati atributul ​de intrare ''​instance'' ​pentru a translata banda desenata pe baza numarului ​de ordine al instantei desenate. +<code cpp> 
-    * Permiteti modificarea ​de la tastatura ​numarului ​de benzi desenate. Acest numar trebuie sa poata fi scazut si crescut+glActiveTexture(GL_TEXTURE0+nr_unitate_texturare);​ 
-    * Dupa acest pas, rezultatul pe care ar trebui ​sa il obtineti ​este urmatorul +glBindTexture(GL_TEXTURE_2Ddepth_texture);​ 
-{{ :​ppbg:​laboratoare:​translation-surface-animation.gif?600 |}} + 
-  - 0.05p - Modificati fisierul ''​GeometryShader.glsl'' ​pentru a desena o suprafata ​de rotatie, pe baza curbei Bézier ​ obtinute anterior. +glUniform1i(glGetUniformLocation(shader->​program,​ "​depth_texture"​),​ nr_unitate_texturare);​ 
-    * Desenati o banda de triunghiuri,​ pe baza tipului de geometrie de iesire ​''​triangle_strip'', ​prin emiterea mai multor varfuri ale caror pozitii se obtin prin esantionarea a doua curbe Bézier, alaturate. +</​code>​ 
-    * Utilizati atributul ​de intrare ''​instance''​ pentru a roti banda desenata pe baza numarului ​de ordine ​al instantei desenate. +  
-    * Permiteti modificarea ​de la tastatura ​numarului de benzi desenate. Acest numar trebuie sa poata fi scazut si crescut+<note tip> 
-    * Permiteti modificarea ​de la tastatura a tipului ​de suprafata ce se deseneaza: suprafata de translatie si de rotatie+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
-    * Dupa acest pas, rezultatul pe care ar trebui ​sa il obtineti ​este urmatorul +  * LearnOpenGL - https://​learnopengl.com/​Advanced-Lighting/​Shadows/​Shadow-Mapping 
-{{ :​ppbg:​laboratoare:​rotation-surface-animation.gif?600 |}}+  * Tipul de date //shadow samplers// - [[https://www.khronos.org/​opengl/​wiki/​Sampler_(GLSL)#​Shadow_samplers]] 
 +</​note>​ 
 + 
 +===== Cerințe laborator ===== 
 + 
 +  - 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 ​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 ​umbrelor și obiectul ​de tip framebuffer implicit pentru pasul 2După 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 ​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 ​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ța 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. 
 +</​note>​
  
 +Bonus: Completaț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:
 +{{ :​ppbg:​laboratoare:​volumetric-illumination.png?​600 |}}
  
ppbg/laboratoare/09.1702495897.txt.gz · Last modified: 2023/12/13 21:31 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