This shows you the differences between two versions of the page.
|
ppbg:laboratoare:09 [2023/12/13 21:34] andrei.lambru |
— (current) | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== Laboratorul 09 ====== | ||
| - | |||
| - | <note tip> | ||
| - | **Reamintire!!!** Puteți prezenta rezolvările cerințelor de până la 2 laboratoare, în fiecare săptămână. De exemplu, puteți prezenta laboratorul curent și pe cel din săptămâna anterioară, în totalitate sau parțial, inclusiv punctajul pentru cerința bonus :) . | ||
| - | </note> | ||
| - | |||
| - | <note tip> | ||
| - | 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. | ||
| - | - 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 ===== | ||
| - | |||
| - | 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: | ||
| - | * 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 plan, indiferent cat de neregulata este forma, se considera curba de forma libera. Aceasta clasa de curbe include si curbele analitice. | ||
| - | |||
| - | ===== Curbe Bézier ===== | ||
| - | |||
| - | 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. | ||
| - | |||
| - | 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 2, 3 si 4 puncte de control arata in felul urmator. | ||
| - | |||
| - | ^ Nr. \\ puncte \\ control ^ Formula ^ Reprezentare vizuala statica ^ Reprezentare vizuala animata | | ||
| - | | 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 |}} | | ||
| - | | 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 ==== | ||
| - | |||
| - | Formula curbei Bézier se poate defini recursiv dupa cum urmeaza: | ||
| - | |||
| - | |||
| - | |||
| - | $$ | ||
| - | B_{n}(P_0, P_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) | ||
| - | $$ | ||
| - | |||
| - | |||
| - | ==== Forma polinomiala ==== | ||
| - | |||
| - | Forma polinomiala a curbei Bézier este dupa cum urmeaza: | ||
| - | |||
| - | |||
| - | $$ | ||
| - | 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 control, forma curbei Bézier, pe baza definitiei de mai sus, arata in felul urmator: | ||
| - | |||
| - | |||
| - | |||
| - | $$ | ||
| - | 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 0 \leq t \leq 1 | ||
| - | $$ | ||
| - | |||
| - | |||
| - | Polinomul urmator, utilizat in definirea formei polinomiale a curbei Bézier, este cunoscut sub numele de polinom Bernstein, dupa numele lui Sergei Bernstein, ce l-a propus in anul 1912: | ||
| - | |||
| - | $$ | ||
| - | b_{i,n}(t) = \binom{n}{i} \cdot t^i \cdot (1-t)^{n-i}, \quad i=0,...,n | ||
| - | $$ | ||
| - | |||
| - | |||
| - | ===== Suprafete generate ===== | ||
| - | |||
| - | 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: | ||
| - | * O geometrie generator, ce este definită explicit si pe baza căreia are loc procesul de generare. | ||
| - | * 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. | ||
| - | |||
| - | ==== 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: | ||
| - | |||
| - | {{ :ppbg:laboratoare:translation-surface.png?600 |}} | ||
| - | |||
| - | ==== 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. | ||
| - | |||
| - | {{ :ppbg: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> | ||
| - | glDrawElementsInstanced(topologie, nr_indecsi, tip_data, offset, instante). | ||
| - | </code> | ||
| - | |||
| - | 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: | ||
| - | |||
| - | <code cpp> | ||
| - | glDrawElementsInstanced(GL_TRIANGLES, 99, GL_UNSIGNED_INT, 0, 1540); | ||
| - | </code> | ||
| - | |||
| - | Instanțierea explicită se face în shader, generând geometrie nouă prin comenzi glsl, în acest caz prin comenzi de geometry shader: | ||
| - | <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> | ||
| - | |||
| - | In situatia in care se utilizeaza instantiere implicita, in 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''. | ||
| - | |||
| - | 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. | ||
| - | |||
| - | {{ :spg:laboratoare:poza_suprafete.png?600 |}} | ||
| - | |||
| - | Din figură 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ă | ||
| - | |||
| - | 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: | ||
| - | |||
| - | {{ :spg:laboratoare:poza_curbe.png?300 |}} | ||
| - | |||
| - | ===== Cerinte laborator ===== | ||
| - | |||
| - | - 0.1p - Modificati fisierul ''GeometryShader.glsl'' pentru a desena o curba Bézier pe baza a 4 puncte de control. | ||
| - | * Utilizati formula specifica unei curbe Bézier cu 4 puncte de control, descrisa 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. | ||
| - | * Permiteti modificarea de la tastatura a numarului de varfuri ce desriu banda de linii. Acest numar trebuie sa poata fi scazut si crescut. | ||
| - | * Dupa acest pas, rezultatul pe care ar trebui sa il obtineti este urmatorul: | ||
| - | {{ :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. | ||
| - | * 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. | ||
| - | * Utilizati atributul de intrare ''instance'' pentru a translata banda desenata pe baza numarului de ordine al instantei desenate. | ||
| - | * Permiteti modificarea de la tastatura a numarului de benzi desenate. Acest numar trebuie sa poata fi scazut si crescut. | ||
| - | * Dupa acest pas, rezultatul pe care ar trebui sa il obtineti este urmatorul: | ||
| - | {{ :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. | ||
| - | * 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. | ||
| - | * Utilizati atributul de intrare ''instance'' pentru a roti banda desenata pe baza numarului de ordine al instantei desenate. | ||
| - | * Permiteti modificarea de la tastatura a numarului de benzi desenate. Acest numar trebuie sa poata fi scazut si crescut. | ||
| - | * Permiteti modificarea de la tastatura a tipului de suprafata ce se deseneaza: suprafata de translatie si de rotatie. | ||
| - | * Dupa acest pas, rezultatul pe care ar trebui sa il obtineti este urmatorul: | ||
| - | {{ :ppbg:laboratoare:rotation-surface-animation.gif?600 |}} | ||
| - | |||