This shows you the differences between two versions of the page.
|
ppbg:laboratoare:09 [2023/12/14 16:32] andrei.lambru [Formă polinomială] |
— (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 formă liberă ===== | ||
| - | |||
| - | Introducem conceptul de curbă de forma liberă pentru a defini acele curbe ce nu pot fi descrise analitic, printr-o formulă închisă. 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 curbă ce poate fi desenată, indiferent de cât de neregulată este forma, se consideră curbă de formă liberă. Această clasa de curbe include și curbele analitice. | ||
| - | |||
| - | ===== Curbe Bézier ===== | ||
| - | |||
| - | Prima curbă de formă liberă ce a fost definită, cronologic, este curba descrisă mai jos ce a fost popularizată de către Pierre Bézier în anii 60'. Aceasta este descrisă inițial de către Paul de Casteljau pentru obținerea unui patent în anul 1959, dar este publicată abia în anii 80'. Cei doi autori au dezvoltat independent parametrizarea acestei forme. | ||
| - | |||
| - | Curba Bézier este o curbă de aproximare ce conține o lista de puncte utilizate pentru a controla forma curbei. Numarul de puncte din lista poate fi oricat de mare. Formulele pentru curba Bézier, in situatia in care este utilizat un numar de 2, 3 și 4 puncte de control, arată în felul urmator. | ||
| - | |||
| - | ^ Nr. \\ puncte \\ control ^ Formulă ^ Reprezentare vizuală statică, t = 0.25 ^ Reprezentare vizuală animată, 0 <= t <= 1 | | ||
| - | | 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 |}} | | ||
| - | |||
| - | ==== Definiție recursivă ==== | ||
| - | |||
| - | Formula curbei Bézier se poate defini recursiv după cum urmează: | ||
| - | |||
| - | |||
| - | |||
| - | $$ | ||
| - | 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) | ||
| - | $$ | ||
| - | |||
| - | |||
| - | ==== Formă polinomială ==== | ||
| - | |||
| - | Forma polinomială a curbei Bézier este după cum urmează: | ||
| - | |||
| - | |||
| - | $$ | ||
| - | 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 definiției de mai sus, arată în felul următor: | ||
| - | |||
| - | |||
| - | |||
| - | $$ | ||
| - | B(t) = (1-t)^3 \cdot P_0 + 3(1-t)^2 \cdot t \cdot P_1 + 3(1-t) \cdot t^2 \cdot P_2 + t^3 \cdot P_3, \quad 0 \leq t \leq 1 | ||
| - | $$ | ||
| - | |||
| - | |||
| - | |||
| - | <note> | ||
| - | Polinomul următor, utilizat în definiția curbei Bézier descrisă mai sus, este cunoscut sub numele de polinom Bernstein, dupa numele lui Sergei Bernstein, ce l-a propus în anul 1912: | ||
| - | |||
| - | $$ | ||
| - | b_{i,n}(t) = \binom{n}{i} \cdot t^i \cdot (1-t)^{n-i}, \quad i=0,...,n | ||
| - | $$ | ||
| - | </note> | ||
| - | |||
| - | |||
| - | ===== 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: | ||
| - | |||
| - | {{ :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_indici, 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> | ||
| - | |||
| - | Î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''. | ||
| - | |||
| - | 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 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ă | ||
| - | |||
| - | 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 |}} | ||
| - | |||
| - | ===== Cerințe laborator ===== | ||
| - | |||
| - | <note tip> | ||
| - | 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. | ||
| - | </note> | ||
| - | |||
| - | - 0.1p - Modificați fișierul ''GeometryShader.glsl'' pentru a desena o curbă Bézier pe baza a 4 puncte de control. | ||
| - | * Utilizați formula specifică unei curbe Bézier cu 4 puncte de control, descrisă mai sus. | ||
| - | * Desenați o bandă de linii, 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 banda de linii. 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: | ||
| - | {{ :ppbg:laboratoare:bezier-animation.gif?600 |}} | ||
| - | - 0.15p - 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: | ||
| - | {{ :ppbg:laboratoare:translation-surface-animation.gif?600 |}} | ||
| - | - 0.05p - 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: | ||
| - | {{ :ppbg:laboratoare:rotation-surface-animation.gif?600 |}} | ||
| - | |||