Differences

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

Link to this comparison view

pgapi:laboratoare:04 [2024/10/04 14:16]
127.0.0.1 external edit
pgapi:laboratoare:04 [2025/09/30 14:29] (current)
andrei.lambru
Line 1: Line 1:
-===== Laboratorul 04 =====+====== Laboratorul 04 ====== 
 +===== Suprafețe generate ​=====
  
-===== Sisteme ​de particule =====+Definim o suprafață generată sub forma unei suprafețe create printr-o metodă ​de multiplicare a unei geometrii suport. Procesul de creare a unei astfel de suprafețe necesită:​ 
 +  * O geometrie generator, ce este definită explicit și pe baza căreia are loc procesul de generare. 
 +  * Un algoritm de generare. Acesta poate fi bazat pe un proces de replicare, urmat de o transformare de translație,​ rotație sau orice alt tip de transformare.
  
-==== Introducere ====+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.
  
-Sistemele ​de particule au fost introduse in grafica cu principalul scop de a reprezenta diferite obiecte ce nu pot fi reprezentate eficient prin geometrie opaca. Obiectele de tip fuzzy, obiectele in care lumina sufera procese de difuzie si diferite fenomene naturale sunt toate implementabile cu mare usurinta prin utilizarea sistemelor de particule.+==== Suprafețe ​de translație ====
  
-Totusi, datorita lipsei ​de capacitate de reprezentare ​unei singure particule, pentru a reprezenta aceste obiecte este nevoie ​de un numar foarte mare de particule, de multe ori de ordinul zecilor si chiar sutelor de mii. De aceea este vital ca particulele sa fie implementate cat mai eficient.+O suprafață ​de translație este o suprafață generată prin instanțierea unui obiect generator. Fiecare instanță ​generatorului suferă o transformare ​de translație. O suprafață ​de translație poate fi definită prin instanțierea unui generator cu fiecare instanță translatată progresiv dupa o funcție.
  
-==== Shader Storage Buffer Objects ====+Un exemplu de suprafață translatată este:
  
-Pentru a implementa eficient particulele vom folosi un nou tip de buffer. Shader storage buffer objects (SSBO) sunt niste tipuri de buffere specifice Shader Model 5 (OpenGL 4.3) ce ofera flexbilitate foarte mare algoritmilor prin faptul ca permit IO direct in shadere (desi exista restrictii).+{{ :​ipg:​laboratoare:​translation-surface.png?600 |}}
  
-Acestea sunt construite ca orice alt buffer ​cu:+==== Suprafețe de rotație ==== 
 + 
 +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. 
 + 
 +{{ :​ipg:​laboratoare:​rotation-surface.png?​600 |}} 
 + 
 +===== Laborator ===== 
 + 
 + 
 +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). 
 + 
 +Pentru a instanția implict geometrie, există comanda:
  
 <code cpp> <code cpp>
-glGenBuffers(1&​buf);​ +glDrawElementsInstanced(topologienr_indicitip_dataoffsetinstante).
-glBindBuffer(GL_SHADER_STORAGE_BUFFERbuf); +
-glBufferData(GL_SHADER_STORAGE_BUFFERdata.size()*sizeof(Data)&​data[0],​ GL_STATIC_DRAW ​);+
 </​code>​ </​code>​
  
-Diferenta cheie fata de celelalte buffere este ca SSBO-urile ​(Shader Storage Buffer Objectssunt legabile la puncte ​de legatura indexateastfel:+De exemplu, dacă se doreste desenarea ​de 1540 de ori (instanțeale unui obiect cu 99 de indici, format din triunghiuri din buffer-ul de indici, legat curent la banda graficăatunci comanda ar fi: 
 <code cpp> <code cpp>
-glBindBufferBase(GL_SHADER_STORAGE_BUFFER,0, buf);+glDrawElementsInstanced(GL_TRIANGLES,​ 99, GL_UNSIGNED_INT, 0, 1540);
 </​code>​ </​code>​
  
-Astfelpe fiecare punct de legatura (GL_SHADER_STORAGE_BUFFER)pot exista mai multe obiecte legate. In shader ​legatura se face in modul urmator+Instanțierea explicită se face în shadergenerând geometrie nouă prin comenzi GLSLîn acest caz prin comenzi de geometry ​shader: 
-<​code>​ +<​code ​glsl
-struct particle+for (int i=0;​i<​10;​i++) ​
- vec4 position; +    ​gl_Position = P*V*M*vec4(p1, 1); EmitVertex()
- vec4 speed+    ​gl_Position = P*V*M*vec4(p2, 1);​ EmitVertex()
- vec4 iposition+    ​gl_Position = P*V*M*vec4(p3, 1); EmitVertex()
- vec4 ispeed; +EndPrimitive();
-        float delay; +
-        float initialDelay+
-        float lifetime; +
-        float initialLifetime;​ +
-};+
  
-layout(std140,​binding=0) buffer particles{ +}
- particle data[]; +
-};+
 </​code>​ </​code>​
  
-Intai este definit tipul de structura tinut in SSBO iar apoi se definiste legatura ​prin layoutPentru a accesa acest buffer ​se poate folosi+În situația în care se utilizează instanțiere implicită, în programul ​de tip vertex shader, ​se poate obține numărul de ordine al instanței din care face parte vârful procesat, ​prin utilizarea atributului de intrare implicit ''​gl_InstanceID''​. 
-<​code>​ + 
-vec3 pos = data[gl_VertexID].position.xyz+<note important>​ 
-vec3 spd data[gl_VertexID].speed.xyz;+În cadrul acestui laborator, ​se utilizează numărul de ordine al instanței din care face parte linia primită la intrare de către programul de tip geometry shader. Implicit, standardul OpenGL nu permite accesul la atributul de intrare ''​gl_InstanceID''​ în geometry shader. Din acest motiv, a fost creat un atribut de ieșire din vertex shader cu numele ''​instance''​ ce este primit sub forma de atribut de intrare în geometry shader cu tipul de date vector de 2 componente ''​instance[2]'',​ conform codului GLSL de mai jos: 
 + 
 +<​code ​glsl
 +// Vertex Shader 
 +..
 +out int instance
 + 
 +void main() 
 +
 +    instance ​gl_InstanceID;​ 
 +    ​..
 +}
 </​code>​ </​code>​
-Pentru sincronizare,​ pe partea de CPU se foloseste: + 
-<​code>​ +<​code ​glsl
-glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);+// Geometry Shader 
 +in int instance[2]; 
 +...
 </​code>​ </​code>​
  
-==== Constructie ====+Ambele valori ale vectorului sunt identice și reprezintă numărul de ordine al instanței din care face parte linia de la intrarea programului de tip geometry shader. 
 +</​note>​ 
 + 
 +Instanțirea oferă posibilitatea ușoară de a crește rapid numărul de obiecte din scenă, dacă obiectele sunt identice. Ex: copaci, tile-uri de teren, unități într-un rts, etc. 
 + 
 +Pentru a lucra cu suprafețe de translație,​ rotaț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.
  
-Un sistem de particule este construit din doua componenteun set de date ce reprezinta o stare initiala sau ciclica si un set de reguli urmate de toate particulele. Din punct de vedere al redarii vizuale particulele urmeaza urmatorul proces: +{{ :pgapi:laboratoare:​poza_suprafete.png?600 |}}
-  - Sunt trimise initial doar ca puncte catre banda grafica, fiecare din particule continand informatii de tipul pozitie curenta, viteza curenta, samd +
-  - In vertex shader sunt calculate noile pozitii si viteze, pentru fiecare particula. Rezultatele sunt scrise inapoi in buffer, direct din shader. +
-  - Apoi in geometry shader se efectueaza o expansiune, transformand punctul intrat in geometrie cu coordonate de texturare. Acest lucru se face exact ca imaginea urmatoare, de obiecei dupa aplicarea transformarii de vizualizare. +
-  - In fragment shader se textureaza/​coloreaza.+
  
-{{ :pgapi:​laboratoare:​particle.png?​direct&​300 |}}+Din imagine se observă clar cum avem mai multe tipuri de obiecte: 
 +  - Obiectul generator (prima linie neagră din stânga) 
 +  - Obiectul nou generat (2 instanțe ale generatorului și topologie de legatură între linii) 
 +  - Suprafața finală generată
  
-<​note> ​  +Dacă nu am fi folosit acest procesatunci prin instanțiere am fi obținut liniile instanțiate,​ dar nu și topologia ​de legatură între liniiadică exact ca în următoarea imagine:
-  * particulele sunt in general limitate de bandwidthcu cat sunt mai multe cu atat sunt mai multe fragmente ce fac citiri din texturi. +
-  * In poza cu laboratorul rezolvat fiecare particula urmareste o ecuatie ​de aruncare +
-  * Daca nu aveti un procesor grafic cu Shader Model 5 puteti utiliza transform feedbackun tutorial ok gasiti aici: http://​ogldev.atspace.co.uk/​www/​tutorial28/​tutorial28.html ​ . Fata de varianta cu SSBO exista o serie de dezavantaje notabile. +
-  * Daca doriti sa comunicati intre invocari de shader trebuie sa aveti un mecanism de sincronizare sau un algoritm in care nu exista race-uri.  +
-  * Exista mai multe layouturi ​ca std140, packed sau std430. Mai multe puteti citi in specificatia OpenGL sau pe scurt in reference: https://​www.opengl.org/​sdk/​docs/​man/​ +
-</​note> ​+
  
 +{{ :​pgapi:​laboratoare:​poza_curbe.png?​300 |}}
  
-==== Cerinte ​laborator ====+===== Cerințe ​laborator ====
  
-  - Descarcati [[https://​github.com/​UPB-Graphics/​gfx-framework|framework-ul de laborator]] +<note tip> 
-  - Creați in geometry shader geometria pentru o particulă (creați un pătrat format din două triunghiuripornind de la un punct) +Prin utilizarea tastelor **1****2****3** și **4**împreună cu combinația acestora cu tastele **SHIFT** ​și **CTRL**puteți controla ​poziția celor 4 puncte de control ​ale curbei Bézier. 
-  - Trimiteți în programul aplicație uniformele către shadere (poziția generatorului (generator_position)timpul estimat pentru prelucrarea unui frame (deltaTime) ​și jumătatea laturii pătratului care reprezintă geometria unei particule (offset)). Dacă task-urile 2 și 3 sunt realizate cum trebuieatunci prima scenă (care este redată când se apasă tasta 1, dar și în mod implicit) - care conține artificiile - ar trebui să se vadă corect +</​note>​
-  - Încărcați texturile de zăpadă, ploaie ​și foc în funcția Init() din programul aplicație +
-  - Legați în funcția Update() texturile corespunzătoare fiecărei scene (zăpadă pentru a doua scenăploaie pentru a treia scenă și foc pentru a patra) +
-  - Completați în programele vertex shader corespunzătoare particulelor de ploaie/​zăpadă și foc, ecuațiile de mișcare (calculează noua poziție a particulei, iar pentru foc se actualizează și durata de viață a particulei). Dacă task-urile ​4,5 și 6 sunt realizate corect atunci se vor afișa și scenele de zăpadă (tasta 2) și de ploaie (tasta 3) +
-  - Completați în geometry shader timpul de viață (geom_lifetime) și timpul de viață inițial (geom_iLifetime) al unei particule. Aveți grijă să completați valorile acestor variabile ÎNAINTE să dați comenzile de emitere de puncte+
-  - Calculați în programul fragment shader corespunzător focului coordonatele ​de textură, astfel încât, în funcție de timpul de viață al particulei, să se afișeze o altă imagine a particulei de foc. Verificați în folder-ul assets modul în care arată o textură de foc (fire.png, fire2.png și fire3.png) - fiecare textură conține patru imagini ​ale stadiului prin care trece o particulă de foc. În programul aplicație este suficient să încărcați o singură textură de foc (puteți să alegeți oricare din fișierele fire.png, fire2.png și fire3.png). Dacă ultimele task-uri sunt realizate corect, atunci și ultima scenă (tasta 3) va fi afișată.+
  
-==== Capturi ​de ecran din aplicație ====+<note important>​ 
 +  * //Geometria suport trimisă către shader este o linie, ce leagă primul și ultimul punct de control.// Punctele de control sunt accesabile în geometry shader sub numele ''​control_p1'',​ ''​control_p2'',​ ''​control_p3'',​ ''​control_p4''​.  
 +  * În laborator, geometria suport pentru curbă este deja definită. Există două tipuri de instanțieri:​ 
 +      * Instanțierea implicită, facută cu comanda glDrawElementsInstanced,​ care este deja implementată și care generează geometria suport de N ori 
 +      * Instanțierea explicită, care va fi implementată în geometry shader. 
 +</​note>​
  
-{{:pgapi:​laboratoare:​fireworks.png?500|}}+  - Descărcați [[https://​github.com/​UPB-Graphics/​gfx-framework|framework-ul de laborator]] 
 +  - Trimiteți către shader numărul de puncte generate pe o curbă bezier (''​no_of_generated_points''​) și controlați de la tastatură atât acest număr (''​no_of_generated_points''​),​ cât și numărul de instanțe (''​no_of_instances''​). 
 +  - Modificați fișierul ''​GeometryShader.glsl''​ pentru a desena o curbă Bézier pe baza a 4 puncte de control. 
 +    * Desenați o polinie, pe baza tipului de geometrie de ieșire ''​line_strip'',​ prin emiterea mai multor vârfuri ale căror poziții se obțin prin eșantionarea curbei Bézier. 
 +    * Permiteți modificarea de la tastatură a numărului de vârfuri ce descriu polilinii. Acest număr trebuie să poată fi scăzut și crescut. 
 +    * După acest pas, rezultatul pe care ar trebui să îl obțineti este următorul: \\ {{ :​ipg:​laboratoare:​bezier-animation.gif?​600 |}} 
 +  - Modificați fisierul ''​GeometryShader.glsl''​ pentru a desena o suprafață de translație,​ pe baza curbei Bézier obținute anterior. 
 +    * Desenați o bandă de triunghiuri,​ pe baza tipului de geometrie de ieșire ''​triangle_strip'',​ prin emiterea mai multor vârfuri ale caror poziții se obțin prin eșantionarea a două curbe Bézier, alăturate. 
 +    * Utilizați atributul de intrare ''​instance''​ pentru a translata banda desenata pe baza numarului de ordine al instanței desenate. 
 +    * Permiteți modificarea de la tastatură a numărului de benzi desenate. Acest număr trebuie să poată fi scăzut și crescut. 
 +    * După acest pas, rezultatul pe care ar trebui să îl obțineti este următorul: \\ {{ :​ipg:​laboratoare:​translation-surface-animation.gif?​600 |}} 
 +  - Modificați fișierul ''​GeometryShader.glsl''​ pentru a desena o suprafață de rotație, pe baza curbei Bézier obținute anterior. 
 +    * Desenați o bandă de triunghiuri,​ pe baza tipului de geometrie de ieșire ''​triangle_strip'',​ prin emiterea mai multor vârfuri ale căror poziții se obțin prin eșantionarea a două curbe Bézier, alăturate. 
 +    * Utilizați atributul de intrare ''​instance''​ pentru a roti banda desenată pe baza numărului de ordine al instanței desenate. 
 +    * Permiteți modificarea de la tastatură a numărului de benzi desenate. Acest număr trebuie să poată fi scăzut și crescut. 
 +    * Permiteți modificarea de la tastatură a tipului de suprafață ce se desenează: suprafață de translație și de rotație. 
 +    * După acest pas, rezultatul pe care ar trebui să îl obțineti este următorul: \\ {{ :ipg:​laboratoare:​rotation-surface-animation.gif?600 |}}
  
-{{:​pgapi:​laboratoare:​snow.png?500|}}+<​hidden>​ 
 +  * Geometria suport trimisă către shader este o linie, ce leagă primul și ultimul punct de control. Punctele de control sunt accesabile în geometry shader sub numele control_p1, control_p2, control_p3, control_p4.  
 +  - Trimiteți către shader numărul de puncte generate pe o curbă bezier (no_of_generated_points) și controlați de la tastatură atât acest număr (no_of_generated_points),​ cât și numărul de instanțe (no_of_instances). 
 +  - Geometria suport va fi în primul rând folosită pentru a genera o curbă de tip Bezier. Pentru acest lucru se vor genera de mână în geometry shader mai multe puncte (no_of_generated_points) pentru care se va evalua curba Bezier. 
 +  - Se vor genera instanțe deplasate ale curbei bezier folosind translații sau rotații 
 +  - Pentru două curbe adiacente, se vor genera triunghiuri,​ ce vor lega geometria generată a instanței curente de geometria generată a instanței următoare, generată prin translație sau rotație (practic se vor lega cate 2 triunghiuri pentru fiecare 2 puncte corespondente de pe 2 curbe - vedeți figura de mai jos). Astfel, plecând de la curbe Bezier, se va crea o suprafață. Modificați output-ul GeometryShader-ului astfel încât să trimita mai departe triangle_strip pentru a procesa corect triunghiurile.
  
-{{:​pgapi:​laboratoare:​rain.png?500|}}+{{ :​pgapi:​laboratoare:​triunghiuri_curbe.png |}} 
 +</​hidden>​
  
-{{:​pgapi:​laboratoare:​fire.png?​500|}} 
pgapi/laboratoare/04.1728040587.txt.gz · Last modified: 2025/09/29 18:21 (external edit)
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