Differences

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

Link to this comparison view

ppbg:laboratoare:02 [2023/10/19 11:24]
andrei.lambru
ppbg:laboratoare:02 [2024/10/16 22:07] (current)
andrei.lambru
Line 1: Line 1:
 ====== Laboratorul 02 ====== ====== Laboratorul 02 ======
  
-<​note ​tip+<​note ​important
-Pentru ​rezolvarea cerințelor din acest laborator, ​aveți nevoie de codul utilizat în rezolvarea cerințelor din cadrul laboratorului 1. În laboratoarele 2 și 3, vom reutiliza acest codÎn situatia în care nu ați rezolvat [[:​ppbg:​laboratoare:​01|laboratorul 1]]va trebui sa îl realizați mai întâi pe el și ulterior ​să reveniți la cerințele celui curent. +Framework-ul de laborator are o proiectare modulară, unde fiecare clasă specifică unui laborator poate fi executată individual. ​Pentru ​a specifica ce laborator ​să fie executattrebuie să modificați fișierul ''​main.cpp''​la linia 49 și să initializați clasa specifică laboratorului dorit. De exemplu, ​pentru inițializarea laboratorului 2, codul arată în felul următor: 
- +<code cpp> 
-**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 :) .+World *world = new lab::Lab2()
 +</​code>​
 </​note>​ </​note>​
  
-<note tip> +===== Banda grafică =====
-**Pentru studenții care au realizat laboratorul pe o versiune a framework-ului datată înainte de 19.10.2023**+
  
-Va trebui să [[https://github.com/​UPB-Graphics/​gfx-framework-ppbg | descărcați]] din nou framwork-ul ​de laborator, deoarece a suferit câteva modificări importante ​și să copiați codul celor 4 metode: ''​ComputeTriangleArea()'',​ ''​CheckPointInsideTriangle()'',​ ''​ComputePixelColor()''​ și ''​ComputePixelDepth()'',​ din versiunea de framework utilizată ​pentru ​rezolvarea cerințelor din laboratorul anterior, în versiunea curentă.+//**Banda grafică** reprezintă secvențde pași ce sunt realizați pentru ​crearea imaginii unui cadru.//
  
-Va fi necesar sa utilizați din nou utilitarul CMake. Pentru a vă reaminti procesul de realizare a setup-ului, puteți să reconsultați [[:​ppbg:​setup-framework | pagina]] dedicată acestui lucru. +<​note ​tip> 
-</note>+Conceptul de //bandă// vine din contextul unei **benzi de asamblare** pentru diferite industrii.
  
-===== Transformări în spații 2D =====+Similar conceptului de bandă de asamblare a unei mașini, schițat ​în imaginea de mai jos, în care de-a lungul mai multor pași, la final rezultă o mașină aproape de forma ei finală, banda grafică reprezintă sunccesiunea de pași care produce la final imaginea unui cadru. Procesul de desenare se încheie la finalul benzii, dar asemănător cu procesul de creare a unei mașini, care mai necesită o serie de pași ulteriori, aplicația mai realizează câteva procese conexe pentru încheierea cadrului.
  
-În laboratorul anterioram văzut cum se poate desena un triunghi pe ecrandacă avem la dispoziție informația necesară pentru fiecare vârf: coordonatele în spațiul 2D, valoarea de adâncime și o culoare. Cu toate acestea, un astfel de sistem nu este suficient de flexibil, deoarece, ​în cadrul unei aplicații grafice în timp real, dorim să realizăm animații cu un model 3D, reprezentat de o rețea de triunghiuri. Coordonatele inițiale ale triunghiurilor trebuie modificate ​pentru ​a realiza o animație. //​Realizarea aceleeași modificări, ​sau transformări,​ pentru toate vârfurile unei rețele ​de triunghiuri,​ produce, din punct de vedere vizual, efectul de aplicare a modificării pentru întreg ansamblul, respectiv ​pentru tot modelul 3D.//+De altfeltraducerea în limba engleză a benzii grafice este **graphics pipeline**ceea ce este similar cu traducerea ​în limba engleză pentru ​banda sau linia de asamblare, respectiv //assembly line//.
  
-Din acest motiv, de-alungul timpului, au fost standardizate mai multe tipuri de modificări asupra informației unui vârf, în particular asupra coordonatelor lui, ce pot fi utilizate în vederea realizării animațiilor.+{{ :​ppbg:​laboratoare:​assembly-line.png?600 |}}
  
-==== Transformarea de translație (deplasare) ====+</​note>​
  
-Transformarea cea mai de bază este cea utilizată pentru modificarea coordonatelor unui vârf. Acest proces se realizeaza prin deplasarea coordonatelor unui vârf cu un anumit vector de deplasare ​șpoartă numele de translație sau translatare.+In continuarea acestui laborator, vom studia doar unul dintre pașii benzii grafice, ce poartă numele de proces de **rasterizare**.
  
-În imaginea de mai jos, în partea dreaptă, se poate observa rezultatul translației pătratului din partea stângă cu vectorul de translație $\vec{t}=\begin{bmatrix} +===== Rasterizatorul =====
-2 & 1 +
-\end{bmatrix}$ .+
  
-{{ :​ppbg:​laboratoare:​translation1.png?​600 |}} +Banda grafică, implementată hardware ​în procesorul grafic ​și software în driver-ul companion tipului ​de procesor, poate fi utilizată în desenarea pe ecran unor suprafețe complexe, ​în situația în care acestea sunt trimise la intrare ​în bandă sub forma unei rețele de triunghiuri. Un astfel de exemplupoate fi văzut ​în imaginea de mai jos, unde trăsăturile feței sunt aproximate ​din unirea ​mai multor triunghiuri
- +
-Formula pentru realizarea procesului de translație este: +
- +
-$$ +
-x'​=x+t_x\\ +
-y'​=y+t_y +
-$$ +
- +
-==== Transformarea de modificare a scării ==== +
- +
-O altă transformarece poate fi utilizată în realizarea animațiilor,​ este modificarea scării unui obiect, respectiv mărirea sau micșorarea obiectului. +
- +
-În imaginea ​de mai josîn partea dreaptă, se poate observa rezultatul modificării scării pentru pătratul din partea stângă, cu vectorul de scară $\vec{s}=\begin{bmatrix} +
-2 & 2 +
-\end{bmatrix}$ . +
- +
-{{ :​ppbg:​laboratoare:​scale1.png?​600 |}} +
- +
- +
-Formula pentru realizarea procesului de modificare ​scării este: +
- +
-$$ +
-x'=s_x \cdot x\\ +
-y'=s_y \cdot y +
-$$ +
- +
-==== Transformarea de rotație ==== +
- +
-Ultima transformare des intalnită ​în grafica pe calculator este rotația unui model. Pentru realizarea acestui proces, pentru spații 2D, vom utiliza un aparat matematic ​care se aplică ​în felul următor: //rotația unui triunghi se realizeaza prin rotația tuturor vârfurilor,​ în sens trigonometric,​ față ​de centrul axelor de coordonate//​. +
- +
-Un exemplu ​pentru această transformare se poate vedea în imaginea de mai jos, unde pătratul este rotit cu 45 de grade, în sens trigonometric,​ față de punctul v0, care este în originea axelor de coordonate. +
- +
-{{ :​ppbg:​laboratoare:​rotation1.png?​600 |}} +
- +
-Formula pentru această transformare este: +
- +
-$$ +
-x'=x \cdot cos(\theta)-y \cdot sin(\theta)\\ +
-y'=x \cdot sin(\theta)+y \cdot cos(\theta) +
-$$ +
- +
-<​note>​ +
-Această formula reiese ​din următorul fapt. Conform imaginii de mai jos, avem punctul V, pe care dorim sa îl rotim cu unghiul B, în sens trigonometric,​ față de originea axelor de coordonate pentru a obține punctul V'. +
- +
- +
-{{ :​ppbg:​laboratoare:​rotation2.png?​200 |}} +
- +
-Componentele x și y ale coordonatei lui V se pot scrie și sub forma: +
- +
- +
-$$ +
-x=r \cdot cos(\alpha)\\ +
-y=r \cdot sin(\alpha) +
-$$ +
- +
-De asemenea, componentele x' și y' ale coordonatei lui V' se pot scrie sub forma: +
- +
- +
- +
-$$ +
-x'=r \cdot cos(\alpha + \beta)\\ +
-y'=r \cdot sin(\alpha + \beta)\\ +
- +
-$$ +
- +
-Continuăm prin înlocuirea sumei din funcțiile trigonometrice cu: +
- +
- +
- +
-$$ +
-x'=r \cdot cos(\alpha) \cdot cos(\beta)-r \cdot sin(\alpha) \cdot sin(\beta)\\ +
-y'=r \cdot cos(\alpha) \cdot sin(\beta)+ r\cdot sin(\alpha) \cdot cos(\beta)\\ +
- +
-$$ +
- +
-În final, înlocuim cu x și y în rezultatul anterior, conform primei formule din această notă și obținem: +
- +
- +
- +
-$$ +
-x'=x \cdot cos(\beta)-y \cdot sin(\beta)\\ +
-y'=x \cdot sin(\beta)+y \cdot cos(\beta) +
-$$+
  
 +{{ :​ppbg:​laboratoare:​rasterizer-1.png?​200 |}}
  
 +<note tip>
 +Noi vom studia, în următoarele 3 laboratoare de la această materie, procesul de desenare pe ecran a unei topologii descrise sub forma unei rețele de triunghiuri. Acest proces cuprinde mai mulți pași.
  
 +<​hidden>​
 +Secvența de pași utilizați în desenarea pe ecran a unei rețele de triunghiuri poartă numele de **bandă grafică** sau, cum este cunoscută în limba engleză, **rendering pipeline**.
 +</​hidden>​
 </​note>​ </​note>​
  
 +În acest laborator, ne vom concentra doar pe un singur pas, de bază, din tot procesul de desenare, mai exact, pasul de desenare în grila de pixeli a ecranului a unor triunghiuri în spațiul 2D. Procesul acesta, în banda grafică, poartă numele de **rasterizare**.
  
-==== Compunerea transformărilor ====+În imaginea de mai jos se poate observa o grilă de pixeli peste care este suprapus un triunghi, marcat in culoarea negru. În culoare albastră a fost marcat centrul fiecărui pixel. Stabilirea pixelilor ce se regasesc în interiorul triunghiului,​ marcați în culoarea verde, se realizează după regula: // dacă centrul unui pixel se află în interiorul triunghiului sau pe latura lui, se consideră ca tot pixelul se află în interiorul triunghiului//​.
  
-Transformarile de bază, prezentate mai sus, nu sunt suficient de flexibile pentru a obține orice tip de animații prin utilizarea individuală a unui anume tip. Un exemplu este rotația față de //propriul centru// al unui pătrat de latură 1 ce a fost definit cu colțul stânga-jos în originea axelor de coordonate. O aplicare directă a transformării de rotație rezultă în rotația pătratului față de colțul stânga-jos. Din acest motiv, este necesar sa obținem rezultatul dorit prin compunerea mai multor transformări. Lanțul de transformări este vizibil în imaginea de mai jos.+{{ :​ppbg:​laboratoare:​rasterizer.png?300 |}}
  
-{{ :​ppbg:​laboratoare:​rotation3.png?​600 |}}+==== Interpolarea informației ====
  
-Transformarea compusă este creată după cum urmează: +Culoarea unui pixel ce se stabilește că se află în interiorul unui triunghi ​este dată de culoarea triunghiului. ​În banda graficăpentru a oferi control utilizatorului,​ culoarea se precizează la nivel de vârf. Astfel, fiecare din cele 3 vârfuri ale unui triunghi conține informație de culoare.
-  - Primul pas este translația pătratului, astfel încat centrul lui să se afle în originea axelor ​de coordonate +
-  - În acest momentputem roti vârfurile pătratului față de centrul lui +
-  - După rotație, pătratul rămâne cu centrul în originea axelor ​de coordonate, astfel că aplicăm transformarea inversă de la punctul 1 pentru a readuce pătratul cu centrul în poziția lui originală+
  
 <note tip> <note tip>
-Același proces ​se poate aplica și pentru transformarea ​de modificare a scării, pentru a face modificarea de scară din centrul pătratului :) .+În laboratorul 8 vom studia o abordare cu care se poate preciza informația la nivel de pixel.
 </​note>​ </​note>​
  
-==== Forma matriceală a transformărilor ====+În situația în care toate cele 3 vârfuri ale unui triunghi au aceeași culoare, toți pixelii ce se regăsesc în interiorul triunghiului au aceeași culoare. În situatia în care vârfurile au culori diferite, culoarea unui pixel se calculează prin interpolare,​ pe baza distanței față de fiecare vârf. Un exemplu vizual se poate găsi în imaginea de mai jos, unde vârful de sus are culoarea albastră, vârful din stânga jos, culoarea roșie și vârful din dreapta jos culoarea verde. Se poate vedea că, un pixel cu cât este mai apropiat de un anumit vârf, cu atât are o nuanță de culoare mai apropiată de cea a vârfului respectiv.
  
-Formula finală obținută în urma compunerii unui lanț de transformări poate fi complexă. De exemplu, formula finală pentru compunerea de mai sus, în care rotim un pătrat față de propriul centru, este:+{{ :ppbg:​laboratoare:​rasterizer-2.jpg?​300 |}}
  
-$$ +Pe lângă informația de culoare, fiecare vârf poate avea asociate și alte dateAceastă abordare poate fi folosită pentru orice tip de informație definită la nivel de vârfuriPuțin mai jos vom vedea o abordare pentru a obține și noi acest rezultat.
-x'​=(x-0.5) \cdot cos(45)-(y-0.5) \cdot sin(45) + 0.5\\ +
-y'​=(x-0.5) \cdot sin(45)+(y-0.5) \cdot cos(45) + 0.5 +
-$$+
  
-Pentru a simplifica și optimiza procesul ​de calcul, se folosește forma matriceală a transformărilor. Pentru acest lucru, vectoriul pentru care se aplică transformarea se scrie, de asemenea, în formă matriceală. În această situație, avem 2 posibilități:​ +==== Testul ​de adâncime ====
-  * Vectorul se scrie sub forma unei matrici cu **o linie și mai multe coloane**, denumit //vector linie//. +
-  * Vectorul se scrie sub forma unei matrici cu **mai multe linii și o singură coloană**, denumit //vector coloană//.+
  
-Ambele reprezentări sunt practicedar atrag după sine forme matriceale diferite pentru transformăriÎn continuarevom lua pe rând ambele forme pentru a vedea reprezentarea lor.+Vom propune, suplimentar,​ ca pe lângă coordonate 2D ''​(xy)'',​ fiecare vârf al unui triunghi să aibă și o coordonată de adâncime ''​(z)''​Această coordonată nu este folosită pentru a stabili dacă un pixel se regăsește în interiorul unui triunghidar este folosită ​pentru ​rezolvarea problemei în care suprafețele ​două triunghiuri se suprapun între ele.
  
-=== Vector linie ===+Pentru a rezolva această situație, trebuie să avem o ordine de afișare. Presupunem că o valoare de adâncime (z) mai mică determină afișarea peste o valoare de adâncime mai mare. Banda grafică hotărăște dacă 2 triunghiuri se pot rasteriza concomitent. Pentru simplitate vom considera că se desenează secvențial exact 2 triunghiuri ce se suprapun. 
 +  - Primul triunghi este rasterizat în totalitate. Pentru fiecare pixel ce se află în interiorul lui, se calculează coordonata de adâncime, prin interpolare între, similar cu abordarea de mai sus, utilizată pentru calcularea culorii. Această coordonată se pastrează într-o grilă separată față de cea utilizata pentru a păstra pixelii. 
 +  - În momentul în care se rasterizează triunghiul 2, și se stabilește un pixel ce se află în interiorul acestui triunghi, se calculează coordonata de adâncime pentru pixel și se compară cu valoarea ce se află la aceeași locație în grila de valori de adâncime. 
 +    - În situația în care valoarea de adâncime a pixelului desenat acum este mai mică decât cea din grilă, se salvează în grila de pixeli și de adâncime, valorile pixelului curent. 
 +    - În situația în care valoarea de adâncime a pixelului desenat acum este mai mare decât cea din grilă, se consideră că pixelul ce trebuie să fie vizibil este deja în grilă și pixelul ce se procesează trebuie să fie în spatele lui, astfel că se renunță la pixelul curent.
  
-Pentru fiecare din cele 3 transformări de bază de mai sus, în situația în care utilizăm un vector linie, forma matriceală este:+==== Laborator ====
  
-$$ 
-\begin{bmatrix} 
-{x+t_x} & {y+t_y} & 1 
-\end{bmatrix} = 
-\begin{bmatrix} 
-x & y & 1 
-\end{bmatrix} ​ 
- ​\begin{bmatrix} 
-1 & 0 & 0\\  
-0 & 1 & 0\\  
-t_x & t_y & 1 
-\end{bmatrix} 
  
 +=== Descrierea rețelei de triunghiuri ===
  
-$$+În framework-ul de laborator, rețeaua de triunghiuri se va descrie prin două structuri de date. Prima este mulțimea ordonată de vârfuri:
  
 +<code cpp>
 +vector<​VertexFormat>​ vertices
 +{
 +    VertexFormat(glm::​vec3(0,​ 50,  0.2f), glm::​vec3(1,​ 0, 0)),
 +    VertexFormat(glm::​vec3(70,​ 99,  0.2f), glm::​vec3(0,​ 1, 0)),
 +    VertexFormat(glm::​vec3(99,​ 0,  0.2f), glm::​vec3(0,​ 0, 1)),
 +    VertexFormat(glm::​vec3(10,​ 10,  0.2f), glm::​vec3(0,​ 1, 1))
 +}
 +</​code>​
  
-$$ +Structura de date ''​VertexFormat''​ conține mai multe informații pentru fiecare vârf. În constructorul ei, primii 2 parametri transmiși sunt poziția (xy, z), cu (xy) în grila de pixeli și coordonata (z) cu valori între 0 și 1, respectiv al doilea parametru este culoarea în modelul de culoare rgb, unde fiecare canal are valorile între ​și 1. Astfel, culoarea roșie este definită ca (1, 00), culoarea verde (0, 1, 0), culoarea cyan (0, 1, 1).
-\begin{bmatrix} +
-{s_x \cdot x} & {s_y \cdot y} & 1 +
-\end{bmatrix} = +
-\begin{bmatrix} +
-1 +
-\end{bmatrix}  +
- ​\begin{bmatrix} +
-s_x & 0\\  +
-& s_y & 0\\  +
-1 +
-\end{bmatrix}+
  
 +A doua structură de date utilizată pentru descrierea rețelei de triunghiuri este o mulțime ordonată de indici ai vârfurilor din prima structură de date:
  
-$$+<code cpp> 
 +vector<​unsigned int> indices 
 +
 +    0, 1, 2, 
 +    0, 2, 3 
 +
 +</​code>​
  
 +Fiecare triplet de indici consecutivi din această mulțime descrie vârfurile care formează un triunghi. De exemplu, tripletul 0, 1, 2 descrie triunghiul format din primele 3 vârfuri din ''​vertices'',​ iar tripletul 0, 2, 3 descrie triunghiul format de primul vârf și ultimele două.
  
 +=== Procesul de rasterizare ===
  
-$$ +<​note ​tip
-\begin{bmatrix} +Procesul ​de rasterizare este implementat ​de cele mai multe ori hardware în procesorul graficdar pentru ​anumite procesoare, este implementat software în driver-ul companion al tipului ​de procesor graficAceste procesoare au arhitecturi closed-source, astfel că metodele utilizate nu sunt publiceDin acest motivîn acest laboratorveți implementa ​versiune didactică a rasterizatoruluice obține rezultate similare ​cu cel utilizat ​de procesorul grafic ​:) .
-{x \cdot cos(\theta)-y \cdot sin(\theta)} & {x \cdot sin(\theta)+y \cdot cos(\theta)} & 1 +
-\end{bmatrix} = +
-\begin{bmatrix} +
-x & y & 1 +
-\end{bmatrix}  +
- ​\begin{bmatrix} +
-cos(\theta) & sin(\theta) & 0\\  +
--sin(\theta) & cos(\theta) & 0\\  +
-0 & 0 & 1 +
-\end{bmatrix} +
- +
- +
-$$ +
- +
-<​note>​ +
-Se poate observa că doar transformarea ​de translație necesită o matrice ​de dimensiune 3x3iar pentru ​celelalte 2 transformări sunt necesare matrici ​de dimensiune 2x2Sunt 2 motive principale pentru care se utilizează matrici de 3x3 pentru toate transformările:​ +
-  * Pentru a realiza transformări compuse, operația de înmulțire între matrici trebuie să fie posibilă, astfel că se utilizează aceeași dimensiune pentru toate tipurile de matrici de transformareMai exactse alege dimensiunea maximă necesară dintre dimensiunile matricelor celor 3 transformări de bazărespectiv 3x3, necesară pentru translație. Astfel, se completează celelalte 2 matrici cu încă o linie și o coloană în căror celule se scrie 0cu excepția celulei (3,3), în care se scrie 1. În plus, la reprezentarea matriceală a vectorului se mai adaugă o celulă ​cu valoarea 1. +
-  * În procesul ​de transformare perspectivă,​ ce va fi utilizat în laboratorul următor, se utilizează coordonate într-un spatiu omogen, ceea ce necesită o informație scalară suplimentară. Vom discuta mai multe detalii în legatură cu acest aspect în laboratorul următor ​:) . +
 </​note>​ </​note>​
  
-Compunerea transformărilor se poate realiza prin înmulțirea matricilor corespunzătoare fiecărei transformări. Astfel, ​pentru ​exemplul de mai sus, în care se rotește un pătrat în jurul propriului centrulanțul de transformări ​este următorul:+Abordarea propusă pentru ​implementare, în acest laborator, este următoarea:
  
 +  * Se parcurg pe rând toți pixelii din dreptunghiul încadrator al triunghiului
 +    * În situația în care centrul pixelului se află în interiorul triunghiului
 +      * Se calculează informația de adâncime a pixelului prin interpolare între vârfuri
 +      * În situația în care testul de adâncime confirmă că acest pixel trebuie să fie vizibil
 +        * Se calculează culoarea pixelului prin interpolare între vârfuri
  
 +<note tip>
 +Centrul unui pixel p, ce se află pe linia ''​r''​ și coloana ''​c''​ în grilă, se consideră că are coordonatele la poziția (c + 0.5, r + 0.5). Numeroatarea liniilor și coloanelor începe de la 0. De exemplu, pentru pixelul aflat pe linia 0 și coloana 0 în grila de pixeli, coordonatele centrului sunt (0.5, 0.5), iar centrul pixelului de pe linia 100 și coloana 150 este la coordonatele (150.5, 100.5).
  
-$$ +Din acest motiv, o grilă de pixeli de rezoluție 1280x720, are ultima coloană egală cu 1279 și ultima linie egală cu 719Observăm că rezoluția unei grile este dată mai întâi de lățime, ce reprezintă numărul de coloane și apoi de înălțime,​ ce reprezintă numărul de linii
-\begin{bmatrix} +</​note>​
-x' & y' & 1 +
-\end{bmatrix} = +
-\begin{bmatrix} +
-x & y & 1 +
-\end{bmatrix}  +
- ​\begin{bmatrix} +
-1 & 0 & 0\\  +
-0 & 1 & 0\\  +
--0.5 & -0.5 & 1 +
-\end{bmatrix} +
- ​\begin{bmatrix} +
-cos(45) & sin(45) & 0\\  +
--sin(45) & cos(45) & 0\\  +
-0 & 0 & 1 +
-\end{bmatrix} +
- ​\begin{bmatrix} +
-1 & 0 & 0\\  +
-0 & 1 & 0\\  +
-0.5 & 0.5 & 1 +
-\end{bmatrix}+
  
 +=== Interpolarea informației din vârfuri ===
  
-$$ +Pentru a calcula informația unui pixel prin interpolare între vârfurise pot folosi coordonatele baricentrice ale centrului pixeluluiAceste coordonate sunt:
- +
- +
-=== Vector coloană === +
- +
-Pentru a obține matricile de transformare,​ în situația în care utilizăm un vector coloanăputem pleca de la forma anterioară,​ în care era utilizat un vector linieAstfel, dacă vrem sa obținem un rezultat transpus celui anterior pentru a aduce forma linie a vectorului la forma coloană, avem:+
  
  
 $$ $$
-\begin{bmatrix} +P'​=(u,​v,​w) \
-x+t_x & y+t_y & 1  +u= \frac{A_{\Delta P V_1 V_2}}{A_{\Delta V_1 V_2 V_3}} \\ 
-\end{bmatrix} ^t =( +v=\frac{A_{\Delta P V_1 V_3}}{A_{\Delta V_1 V_2 V_3}} \\ 
- +w=\frac{A_{\Delta P V_2 V_3}}{A_{\Delta V_1 V_2 V_3}} \\
-\begin{bmatrix+
-x&  +
-y&  +
-+
-\end{bmatrix}  ​\begin{bmatrix} +
-1 & 0 & 0\\  +
-0 & 1 & 0\\  +
-t_x & t_y & 1 +
-\end{bmatrix})^t+
 $$ $$
  
 +Aceste coordonate sunt descrise prin raportul dintre ariile unuia dintre triunghiurile interioare din imaginea de mai jos și aria triunghiului mare.
  
-Deoarece, conform următoarei proprietăți a matricilor:+{{ :ppbg:​laboratoare:​rasterizer-4.png?​200 |}}
  
 +Pentru calcularea culorii punctului se folosește:
  
  
 $$ $$
-(M_{0} \cdot M_{1} \cdot ... \cdot M_{n-1} \cdot M_{n})^{t} ​M_{n}^{t} ​\cdot M_{n-1}^{t} \cdot ... \cdot M_{1}^{t}\cdot ​M_{0}^{t}+C_P\cdot C_{V_3+ v \cdot C_{V_2+ w \cdot C_{V_1}
 $$ $$
  
-Rezultă că forma matricei ​pentru ​transformarea ​de translație este+Această abordare poate fi utilizată pentru ​a calcula prin interpolare între vârfuri orice tip de informație asociată vârfurilor. De exemplu, pentru a calcula valoarea de adâncime a unui pixel, descrisă mai sus, se folosește:
  
-$$ 
-\begin{bmatrix} 
-x+t_x \\ y + t_y \\ 1  
-\end{bmatrix} ​ = 
  
- ​\begin{bmatrix} 
-1 & 0 & 0\\  
-0 & 1 & 0\\  
-t_x & t_y & 1 
-\end{bmatrix}^t ​ 
-\begin{bmatrix} 
-x& ​ 
-y& ​ 
-1 
-\end{bmatrix} ^t= 
- ​\begin{bmatrix} 
-1 & 0 & t_x\\  
-0 & 1 & t_y\\  
-0 & 0 & 1 
-\end{bmatrix} 
  
-\begin{bmatrix} 
-x\\  
-y\\  
-1 
-\end{bmatrix} ​ 
 $$ $$
- +Z_P= u \cdot Z_{V_3} + v \cdot Z_{V_2} + w \cdot Z_{V_1}
-Analog pentru matricile celorlalte 2 transformări:​ +
- +
 $$ $$
-\begin{bmatrix} 
-s_x \cdot x \\ s_y \cdot y \\ 1  
-\end{bmatrix} ​ = 
- ​\begin{bmatrix} 
-s_x & 0 & 0\\  
-0 & s_y & 0\\  
-0 & 0 & 1 
-\end{bmatrix} 
  
-\begin{bmatrix} 
-x\\  
-y\\  
-1 
-\end{bmatrix} ​ 
-$$ 
  
  
 +===== Cerințe laborator =====
  
-$$ +Completați clasa ''​TriangleRasterizer''​ cu următoarele:​ 
-\begin{bmatrix} +  0.15p - Completați metodele ''​CheckPointInsideTriangle()''​ și ''​ComputeTriangleArea()''​ pentru a calcula dacă un punct se află în interiorul unui triunghi, conform indicațiilor de mai sus. 
-x \cdot cos(\theta)-y \cdot sin(\theta\\ x \cdot sin(\theta)+y \cdot cos(\theta\\ 1 +  - 0.1p - Completați metoda ''​ComputePixelColor()''​ pentru a calcula informația de culoare prin interpolare între vârfuri. Utilizați coordonatele baricentrice,​ descrise mai sus. 
-\end{bmatrix} ​ +  - 0.05p - Completați metoda ''​ComputePixelDepth()''​ pentru a calcula informația de adâncime prin interpolare între vârfuri. Utilizați coordonatele baricentrice,​ descrise mai sus.
- ​\begin{bmatrix} +
-cos(\theta) & -sin(\theta) & 0\\  +
-sin(\theta& cos(\theta) & 0\\  +
-0 & 0 & 1 +
-\end{bmatrix}+
  
-\begin{bmatrix} +Rezultatul final pe care ar trebui să îl obțineti este următorul:
-x\\  +
-y\\  +
-+
-\end{bmatrix}  +
-$$+
  
-Pentru transformarea compusă dată exemplu mai devreme, vom avea: +{{ :​ppbg:​laboratoare:​rasterizer-5.png?600 |}}
- +
- +
- +
-$$ +
-\begin{bmatrix} +
-x' \\ y' \\ 1 +
-\end{bmatrix} = +
- ​\begin{bmatrix} +
-1 & 0 & 0.5\\  +
-0 & 1 & 0.5\\  +
-0 & 0 & 1 +
-\end{bmatrix} +
- ​\begin{bmatrix} +
-cos(45) & -sin(45) & 0\\  +
-sin(45) & cos(45) & 0\\  +
-0 & 0 & 1 +
-\end{bmatrix} +
- ​\begin{bmatrix} +
-1 & 0 & -0.5\\  +
-0 & 1 & -0.5\\  +
-0 & 0 & 1 +
-\end{bmatrix} +
- +
-\begin{bmatrix} +
-x \\ y \\ 1 +
-\end{bmatrix +
- +
-$$+
  
 <note tip> <note tip>
-Observăm ​, in situația în care utilizăm un vector coloană, ordinea ​de aplicare ​transformărilor este **de la ultima matrice la prima**În plusvectorul pentru care se aplică lanțul ​de transformări este întotdeauna la final.+Se poate observa ​că fiecare din cele două triunghiuri se află parțial în spate și parțial în fața celuilalt. Acest rezultat este obținut deoarece triunghiul ce are în vârfuri culorile roșuverde și albastru are toate coordonatele ​de adâncime egale cu 0.5, iar triunghiul ce are în vârfuri culorile galben, magenta și cyan, are coordonata de adâncime ​vârfului de culoare cyan egală cu 0 și coordonatele ​de adâncime a celorlalte 2 vârfuri egale cu 1Din acest motivapare efectul ​de întretăiere a celor două triunghiuri.
 </​note>​ </​note>​
  
-<note+<hidden
-În cadrul laboratoarelor de la această materie, până la finalul semestrului,​ vom utiliza reprezentarea unui vector în formă coloană. Ambele reprezentări ale vectorilor sunt practice și compatibile cu procesorul grafic. +Bonus
-</​note>​ +  - Generati ​ geometria ​pentru ​un cerc format ​din mai multe triunghiuri 
- +</hidden>
-=== Biblioteca glm === +
- +
-În cadrul laboratoarelor de la această materie, vom utiliza biblioteca glm pentru gestionarea matricilor și a operațiilor cu matrici. +
- +
-La bază, biblioteca glm folosește matrici column-major,​ mai precis, matrici care au informația transpusă în memorie. Astfel, în constructorul tipului de date ''​glm::​mat3'',​ trebuie transmisă forma transpusă a matricei pe care dorim sa o reținem. +
- +
-De exemplu, matricea pentru transformarea de translație,​ utilizată pentru inmulțirea cu un **vector coloană**, trebuie inițializată astfel: +
- +
-<code cpp> +
-glm::mat3 Translate(float tx, float ty) +
-+
- return glm::mat3(  +
-        1,  0, 0,     // coloana 1 in memorie  +
- 0,  1, 0,     // coloana 2 in memorie  +
- tx, ty, 1);    // coloana 3 in memorie  +
-                +
-+
-</​code>​ +
- +
-De asemenea, avem opțiunea să inițializăm matricea în formă netranspusă și să aplicăm ''​glm::​transpose''​ ulterior: +
- +
-<code cpp> +
-glm::mat3 Translate(float tx, float ty) +
-+
- return glm::​transpose( +
- glm::​mat3( 1, 0, tx,  +
-    0, 1, ty,  +
-    0, 0, 1) +
- );  +
-+
-</​code>​ +
- +
-==== Transformarea fereastră-poartă ==== +
- +
-În situatia în care dorim ca aplicația grafică proiectată de noi să nu depindă de rezoluția ferestrei și astfel să poată funcționa la rezoluții diferite, trebuie să nu mai definim coordonatele vârfurilor în grila de pixeli a ecranului. Pentru acest proces, vom defini un spațiu special, finit, denumit spațiu logic, în care vom declara coordonatele vârfurilor. Acest spațiu este o fereastră peste spațiul 2D și din acest motiv, transformarea are numele de transformare fereastră-poartă,​ respectiv transformare din fereastra peste spațiul 2D în poarta de vizualizare,​ reprezentată de ecran. +
- +
-În laborator, a fost definit spațiul logic, după cum urmează: +
- +
-<code cpp> +
-struct LogicSpace +
-+
-    float x; +
-    float y; +
-    float width; +
-    float height; +
-}; +
-</​code>​ +
- +
-Se poate observa ca acest spațiu este definit de coordonatele calțului stânga-jos pentru fereastra și de o lățime și o înălțime a acesteia. +
- +
-Analog, realizăm o structură de date pentru poarta de vizualizare,​ cunoscută în limba engleza sub numele de viewport: +
- +
-<code cpp> +
-struct ViewportSpace +
-+
-    int x; +
-    int y; +
-    int width; +
-    int height; +
-}; +
-</​code>​ +
- +
-De exemplu, pentru a transforma obiectele definite în spatiul logic ce are colțul stânga-jos la coordonatele (1, 1) și rezoluția de 3x2, astfel încât să fie puse pe întreg ecranul, de rezoluție 1280x720, se pot defini spațiile în felul următor. +
- +
-<code cpp> +
-ViewportSpace viewport_space = { 0, 0, 1280, 720 }; +
-LogicSpace logic_space = { 1, 1, 3, 2 }; +
-</​code>​ +
- +
-Transformarea se poate urmări vizual în imaginea de mai jos. +
- +
-{{ :​ppbg:​laboratoare:​viewport.png?​600 |}} +
- +
-Lanțul de transformări necesar acestui proces este: +
- +
- +
- +
-$$ +
-\begin{bmatrix} +
-x' \\ y' \\ 1 +
-\end{bmatrix} = +
- ​\begin{bmatrix} +
-1 & 0 & V_{x}\\  +
-0 & 1 & V_{y}\\  +
-0 & 0 & 1 +
-\end{bmatrix} +
- ​\begin{bmatrix} +
-V_{w}/L_{w} & 0 & 0\\  +
-0 & V_{h}/L_{h} & 0\\  +
-0 & 0 & 1 +
-\end{bmatrix} +
- ​\begin{bmatrix} +
-1 & 0 & -L_x\\  +
-0 & 1 & -L_y\\  +
-0 & 0 & 1 +
-\end{bmatrix} +
- +
-\begin{bmatrix} +
-x \\ y \\ 1 +
-\end{bmatrix}  +
- +
-$$ +
- +
- +
-==== Cerințe laborator ==== +
- +
-  - 0.1p - Completați fișierul ''​transform2D.h''​ cu cele 4 transformări descrise mai sus. +
-  - 0.05p - Aplicați transformările necesare ​pentru ​a modifica pătratele de pe linia din partea de sus, conform rezultatului din imaginea de mai jos. Consultați comentariile din cod pentru a primi mai multe detalii despre fiecare transformare. +
-  - 0.1p - Aplicați transformările necesare pentru a modifica pătratele de pe linia din partea de jos, conform rezultatului din imaginea de mai jos. Consultați comentariile din cod pentru a primi mai multe detalii despre fiecare transformare. \\ Pâna în acest punct, rezultatul pe care ar trebui să îl obțineti este următorul: {{ :​ppbg:​laboratoare:​transformations1.png?​600 |}} +
-  - 0.05p - Împărțiți ecranul în 4 cadrane și desenați formele geometrice de mai sus de 4 ori, câte o dată în fiecare cadran. Modificați spațiul porții de vizualizare,​ coordonatele colțului din stânga jos, respectiv, lățimea și înălțimea. +
- +
-Rezultatul final ar trebui să fie urmatorul:​ +
- +
-{{ :​ppbg:​laboratoare:​transformations2.png?​600 |}} +
- +
-<note tip> +
-Utilizați tastele **sus**, **jos**, **stânga** și **dreapta** pentru a controla interactiv pozitia colțului din stânga-jos a spațiului logic. +
-</​note>​ +
- +
-Bonus: Realizați razele unei stele prin desenarea multiplă a unui triunghi rotit la unghiuri diferite. Este necesar să construiți o nouă geometrie pentru triunghiul ce reprezintă o rază. Un exemplu vizual ar putea fi: +
- +
-{{ :​ppbg:​laboratoare:​transformations3.png?​600 |}} +
- +
-<note tip> +
-  * Aveți în vedere că, pentru simplitate, triunghiul ce reprezintă raza, poate fi creat direct cu proprietatea de a fi isoscel :) . +
-  * Razele **se pot** suprapune între ele. +
-</note>+
  
ppbg/laboratoare/02.1697703847.txt.gz · Last modified: 2023/10/19 11:24 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