Differences

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

Link to this comparison view

pgapi:laboratoare:05 [2024/10/04 14:16]
127.0.0.1 external edit
pgapi:laboratoare:05 [2025/09/29 18:21] (current)
andrei.lambru
Line 1: Line 1:
 ===== Laboratorul 05 ===== ===== Laboratorul 05 =====
  
-===== Deferred Rendering ​=====+===== Sisteme de particule ​=====
  
 ==== Introducere ==== ==== Introducere ====
  
-Pentru ​desena ​obiecte ​iluminate 3D metoda studiată până acum este prin aplicarea directă a calculelor de iluminare (iluminare în vertex sau fragment shader) pentru a determina culorile pixelilor suprafețelor desenateAceastă tehnică se numește forward rendering.+Sistemele de particule au fost introduse in grafica cu principalul scop de reprezenta diferite ​obiecte ​ce nu pot fi reprezentate eficient ​prin geometrie opacaObiectele 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.
  
-Tehnica forward rendering nu se scalează bine când sunt multe surse de lumină deoarece se realizează calculele ​de iluminare și pentru ​pixelii unor suprafețe care sunt pe urmă obturați ​de pixelii altor suprafețe care sunt mai apropiați ​de observator.+Totusi, datorita lipsei ​de capacitate ​de reprezentare a 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.
  
-Pentru multe surse de lumină este avantajos să realizăm calculele de iluminare doar pentru pixelii care râmăn afișați în final pe ecran.+==== Shader Storage Buffer Objects ====
  
-Deferred Rendering este o tehnică avansată, extensibilă si versatilă ​de sinteză în timp real de imagini ale obiectelor dintr-o scenă 3DCu un nume sugestiv, '​intârziat'​ sau '​amânat',​ tehnica se bazează pe desenarea ​de informație a geometriei din fiecare pixel(poziție in spațiul lume, vectorul normal în spațiul lume, constanta difuză, constanta speculară, strălucirea etc.) în texturi separate într-un prim pas, amânând procesul de iluminare pentru un pas urmator. Astfel când începe procesul de iluminare se vor folosi informațiile pixelilor celor mai apropiați de observator.+Pentru a implementa eficient particulele vom folosi un nou tip de bufferShader 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).
  
-==== Forward Rendering ==== +Acestea ​sunt construite ca orice alt buffer cu:
-In forward rendering culoarea finală a unui pixel se obține prin contribuția fiecărui fragment afișat in acel pixel, iar pentru culoarea fragmentelor se evaluează contribuția de la fiecare lumină din scenă. Din cauza aceasta, ​sunt evaluate fragmente ce vor fi acoperite ulterior sau se calculează contribuția neglijabilă a unei lumini îndepărtate.+
  
-==== Deferred Rendering ==== +<code cpp> 
-In deferred renderingecuația de iluminare nu se mai execută pentru fiecare combinație posibilă ​(obiectlumina), ci doar pentru luminile ce garantat au o contribuție ne-neglijabila.+glGenBuffers(1&​buf);​ 
 +glBindBuffer(GL_SHADER_STORAGE_BUFFERbuf)
 +glBufferData(GL_SHADER_STORAGE_BUFFERdata.size()*sizeof(Data),​ &​data[0],​ GL_STATIC_DRAW ); 
 +</​code>​
  
-Acest lucru se face in 3 etape: +Diferenta cheie fata de celelalte buffere este ca SSBO-urile (Shader Storage Buffer Objectssunt legabile la puncte ​de legatura indexateastfel: 
-  ​GEOMETRY PASS: evaluarea informațiilor geometrice si texturale per pixel +<code cpp> 
-  - LIGHT ACCUMULATION PASS: folosind functia de blend (GL_ONE, GL_ONE), se acumulează într-o textură rezultatul calculului ​de iluminare pentru fiecare luminăutilizând informațiile geometrice randate în G-buffer la pasul 1. +glBindBufferBase(GL_SHADER_STORAGE_BUFFER,​0buf)
-  - FINAL(COMPOSITION) PASS: se evaluează culoarea finală a pixelului ca funcție de iluminarea acumulată la pasul anterior și de informațiile texturale(și poate și geometricee.g. rim light etc.)+</​code>​
  
-=== Geometry Buffer ===+Astfel, pe fiecare punct de legatura (GL_SHADER_STORAGE_BUFFER),​ pot exista mai multe obiecte legate. In shader legatura se face in modul urmator: 
 +<​code>​ 
 +struct particle{ 
 + vec4 position; 
 + vec4 speed; 
 + vec4 iposition;​ 
 + vec4 ispeed; 
 +        float delay; 
 +        float initialDelay;​ 
 +        float lifetime; 
 +        float initialLifetime;​ 
 +};
  
-Pentru a implementa deferred renderingvom folosi un frame buffer ​mare, denumit Geometry Buffer, sau G-Buffer. Acesta are atașate mai multe render textures utilizând GL_COLOR_ATTACHMENT_i. +layout(std140,binding=0) ​buffer ​particles{ 
-{{:​pgapi:​laboratoare:​g-buffer.png?​500|}}+ particle data[]; 
 +}
 +</​code>​
  
-=== Geometry Pass === +Intai este definit tipul de structura tinut in SSBO iar apoi se definiste legatura prin layout. Pentru a accesa acest buffer se poate folosi: 
-In această etapă sunt completate urmatoarele render targets din G-buffer: +<​code>​ 
-  * adâncime(se face automat) +vec3 pos data[gl_VertexID].position.xyz;​ 
-  * poziție +vec3 spd data[gl_VertexID].speed.xyz;​ 
-  * normală +</​code>​ 
-  * culoare+Pentru sincronizare,​ pe partea de CPU se foloseste: 
 +<​code>​ 
 +glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);​ 
 +</​code>​
  
-=== Light Accumulation Pass === +==== Constructie ====
-In această etapă sunt completate intrările din G-buffer pentru acumularea de lumină.+
  
-Pentru a calcula intersecția intre obiecte și lumini vom folosi obiecte geometrice aferente luminilorsfera cu rază egala cu distanța maximă ​de influență pentru lumina omnidirectionalăcon cu sferă în baza pentru ​spot light(nu e implementat ​in laborator).+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: 
 +  - 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.
  
-Pentru fiecare fragment de obiect ce reprezintă o lumină se încarcă poziția si normala din G-buffer și se evaluează ecuația de iluminare. Rezultatul este acumulat in bufferul de acumulare din G-buffer.+{{ :​pgapi:​laboratoare:​particle.png?​direct&​300 |}}
  
-=== Final Pass ===+<​note> ​  
 +  * particulele sunt in general limitate de bandwidth, cu 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 feedback, un 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> ​
  
-In aceasta etapă se calculează rezultatul final per pixel. Culoarea nu se scrie in G-buffer, ci direct in framebuffer-ul default (cel al ferestrei grafice) sau în altul pregatit pentru postprocesare. Se combină culoarea pixelului cu iluminarea calculată și cu lumina ambientală. 
  
-{{:​pgapi:​laboratoare:​deferred.png?​735|}}+==== Cerinte laborator ====
  
 +  - Descarcati [[https://​github.com/​UPB-Graphics/​gfx-framework|framework-ul de laborator]]
 +  - Creați in geometry shader geometria pentru o particulă (creați un pătrat format din două triunghiuri,​ pornind de la un punct)
 +  - 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 trebuie, atunci 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
 +  - Î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ă.
  
-==== Avantaje ​==== +==== Capturi de ecran din aplicație ​====
-  - Desenarea informațiilor geometrice este eficientă deoarece nu se fac calcule de iluminare. Astfel se determină rapid pixelii cei mai apropiați de observator. +
-  - Pentru sursele de lumină de intensitate mică se vor realiza calculele de iluminare într-o zonă restrânsă pe ecran. Astfel se evită calcularea contribuției fiecărei surse de lumină pentru fiecare pixel de pe ecran. +
-  - Extensibilitatea,​ facilitează compoziția cu diverse etape de postprocesare ale informațiilor vizuale(de exemplu detecția contururilor folosind textura de normale și/sau textura de adâncime; efecte de bloom sau strălucire etc.) +
-  - Nu mai este necesară scrierea de fragment shadere care să primească ca variabile de tip uniform o listă cu sursele de lumină. În pasul de iluminare pentru fiecare sursă de lumină se folosește un shader care tratează doar acea sursă de lumină. +
-  - Având N obiecte și L surse de lumină complexitatea tehnicii deferred este O(N + L), în timp ce complexitatea forward rendering este O(N * L). De ce? Se separă buclele iterative peste mulțimea de lumini si mulțimea de obiecte din scenă:+
  
- Forward: +{{:pgapi:laboratoare:fireworks.png?​500|}}
- for (obiect in obiecte): +
- for (lumina in lumini): +
- calculeaza_iluminarea(lumina,​ obiect)+
  
- Deferred: +{{:pgapi:laboratoare:snow.png?​500|}}
- for (obiect in obiecte): +
- deseneaza(obiect,​ Gbuffer) +
- for (lumina in lumini): +
- deseneaza(lumina)+
  
-==== Dezavantaje ==== +{{:pgapi:​laboratoare:​rain.png?500|}}
-  +
-  - Complexitatea algoritmului poate fi dezavantajoasă dacă sunt puține surse de lumină în scenă +
-  - Nu se pot folosi metode de netezire a muchiilor folosind accelerație hardware ([[https://www.khronos.org/​opengl/​wiki/​Multisampling#​Multisamplingmultisampling]]). În schimb se pot folosi soluții de sinteză avansată de anti-aliasing,​ precum SSAA, MSAA, FXAA(foarte rapid), TAA, etc. +
-  - Pentru fiecare informație a suprafeței necesară calculelor de iluminare este necesară adăugarea acestora în G-Buffer pentru fiecare pixel pe ecran. Astfel, se încarcă memoria procesorului grafic. +
-  - Din cauză că deferred rendering se bazează pe faptul că un singur obiect va fi vizibil per pixel, algoritmul funcționează cât timp obiectele din scenă sunt opace. Obiectele transparente trebuie desenate în alt mod.+
  
-==== Cerințe laborator ====+{{:​pgapi:​laboratoare:​fire.png?​500|}}
  
-  - Descărcați [[https://​github.com/​UPB-Graphics/​gfx-framework|framework-ul de laborator]] 
-  - Completați în metoda ''​Init'',​ atribuirea pentru fiecare din cele 40 de surse de lumină din scenă a unei poziții, a unei raze și a unei culori alese aleator. 
-  - Pentru fiecare sursă de lumină, desenați o sferă la poziția ei, cu o rază egală cu dublul razei de influență a acesteia. Setați variabilele ''​light_position'',​ ''​light_color''​ și ''​light_radius'',​ de tipul uniform, cu informațiile sursei de lumină. 
-  - În fișierul ''​LightPass.FS.glsl''​ eșantionați texturile din G-buffer și folosiți metoda PhongLight pentru a calcula influența sursei de lumină ce va fi acumulată. 
-  - Completați în fișierul ''​Composition.FS.glsl'',​ calculul de compoziție între culoarea obiectelor și influența luminilor asupra obiectelor. 
-  - Realizați o animație de orbitare a surselor de lumină. Orbita pentru fiecare sursă de lumină este în jurul centrului scenei față de axa Oy. 
pgapi/laboratoare/05.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