Laboratorul 02

Suprafețe generate

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.

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.

Suprafețe de translație

O suprafață de translație este o suprafață generată prin instanțierea unui obiect generator. Fiecare instanță a 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.

Un exemplu de suprafață translatată este:

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.

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:

glDrawElementsInstanced(topologie, nr_indici, tip_data, offset, instante).

De exemplu, dacă 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:

glDrawElementsInstanced(GL_TRIANGLES, 99, GL_UNSIGNED_INT, 0, 1540);

Instanțierea explicită se face în shader, generând geometrie nouă prin comenzi GLSL, în acest caz prin comenzi de geometry shader:

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();
 
}

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

Î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:

// Vertex Shader
...
out int instance;
 
void main()
{
    instance = gl_InstanceID;
    ...
}
// Geometry Shader
in int instance[2];
...

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.

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.

Din imagine se observă clar cum avem mai multe tipuri de obiecte:

  1. Obiectul generator (prima linie neagră din stânga)
  2. Obiectul nou generat (2 instanțe ale generatorului și topologie de legatură între linii)
  3. Suprafața finală generată

Dacă nu am fi folosit acest proces, atunci prin instanțiere am fi obținut liniile instanțiate, dar nu și topologia de legatură între linii, adică exact ca în următoarea imagine:

Cerințe laborator

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.

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

  1. 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).
  2. 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:
  3. 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:
  4. 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:
pgapi/laboratoare/02.txt · Last modified: 2024/10/09 10:05 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