Laboratorul 04

Sisteme de particule

Introducere

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.

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.

Shader Storage Buffer Objects

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).

Acestea sunt construite ca orice alt buffer cu:

glGenBuffers(1, &buf);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, buf);
glBufferData(GL_SHADER_STORAGE_BUFFER, data.size()*sizeof(Data), &data[0], GL_STATIC_DRAW );

Diferenta cheie fata de celelalte buffere este ca SSBO-urile (Shader Storage Buffer Objects) sunt legabile la puncte de legatura indexate, astfel:

glBindBufferBase(GL_SHADER_STORAGE_BUFFER,0, buf);

Astfel, pe fiecare punct de legatura (GL_SHADER_STORAGE_BUFFER), pot exista mai multe obiecte legate. In shader legatura se face in modul urmator:

struct particle{
	vec4 position;
	vec4 speed;
	vec4 iposition;
	vec4 ispeed;
        float delay;
        float initialDelay;
        float lifetime;
        float initialLifetime;
};

layout(std140,binding=0) buffer particles{
	particle data[];
};

Intai este definit tipul de structura tinut in SSBO iar apoi se definiste legatura prin layout. Pentru a accesa acest buffer se poate folosi:

vec3 pos = data[gl_VertexID].position.xyz;
vec3 spd = data[gl_VertexID].speed.xyz;

Pentru sincronizare, pe partea de CPU se foloseste:

glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);

Constructie

Un sistem de particule este construit din doua componente: un 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:

  1. Sunt trimise initial doar ca puncte catre banda grafica, fiecare din particule continand informatii de tipul pozitie curenta, viteza curenta, samd
  2. In vertex shader sunt calculate noile pozitii si viteze, pentru fiecare particula. Rezultatele sunt scrise inapoi in buffer, direct din shader.
  3. 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.
  4. In fragment shader se textureaza/coloreaza.

  • 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/

Cerinte laborator

  1. Creați in geometry shader geometria pentru o particulă (creați un pătrat format din două triunghiuri, pornind de la un punct)
  2. 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
  3. Încărcați texturile de zăpadă, ploaie și foc în funcția Init() din programul aplicație
  4. 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)
  5. 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)
  6. 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.
  7. 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

spg/laboratoare/04.txt · Last modified: 2023/10/27 08:09 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