This shows you the differences between two versions of the page.
egc:teme:2019:10 [2019/12/05 09:26] andrei.lambru removed |
— (current) | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | <hidden> | ||
- | ======= Tema 3 - Worms 3D ======= | ||
- | * **Responsabili:** Cristian Lambru | ||
- | * **Lansare:** 6 decembrie | ||
- | * **Termen de predare:** 12 ianuarie 2020, ora 23:55 | ||
- | * **Notă: Orice informație ce nu a fost acoperită în acest document este la latitudinea voastră!** | ||
- | |||
- | În cadrul temei 2 trebuie să implementați un joc în care sunteți un aviator ce nu trebuie să se lovească de obstacole și nici să rămână fără combustibil pentru avion. | ||
- | |||
- | ====== Construcția terenului ===== | ||
- | |||
- | ===== Harta de inălțimi ===== | ||
- | |||
- | Definim o suprafață de baleiere descrisă de funcția: | ||
- | |||
- | $$ | ||
- | f(x,z) = y | ||
- | $$ | ||
- | |||
- | Datorită construcției, o astfel de suprafață poate fi determinată direct de conținutul unei texturi în următorul mod: | ||
- | |||
- | $$ | ||
- | f(x,z) = texture2D(unitTexture,vec2 (u,v)).r | ||
- | $$ | ||
- | |||
- | unde $\{u, v\}$ reprezintă coordonatele de textură asociate coordonatelor spațiale $\{x,z\}$. | ||
- | |||
- | Aceste tipuri de texturi, care descriu suprafețe de baleiere, se numesc hărți de inalțime sau **height maps**. Ele conțin în fiecare pixel o singură informație în $[0,255]$ (normalizată $[0,1]$), pe un singur canal, ce reprezintă înălțimea zonei acoperite de pixelul respectiv. Un exemplu de astfel de textură se poate vedea mai jos. | ||
- | |||
- | {{ :egc:teme:2019:heightmap.png?nolink&200 |}} | ||
- | |||
- | ===== Geometria suport ===== | ||
- | |||
- | Pentru a putea crea o suprafață definită de înălțimea dată de textură este necesară o geometrie suport care să cuprindă toate coordonatele $\{x,z\}$ finale. De asemenea, este necesar ca fiecărui vertex să i se asocieze o coordonată de textură, $\{u,v\} \in [0, 1]$, normalizată între limitele pe $x$ și pe $y$ ale geometriei suport. | ||
- | |||
- | {{ :egc:teme:2019:terrain1.png?nolink&600 |}} | ||
- | |||
- | Geometria suport se desenează cu un shader special, care la pasul de vertex shader accesează textura în care se află înălțimile. Prin interogarea texturii se obține înălțimea de la coordonatele $\{u,v\} \in [0,1]$, asociate vertexului. Această valoare se poate asocia direct coordonatei $y$ a vertexului sau se poate scala pentru un impact mai mare al terenului. | ||
- | |||
- | {{ :egc:teme:2019:terrain2.png?nolink&600 |}} | ||
- | |||
- | ===== Calculul normalelor ===== | ||
- | |||
- | Pentru a putea lumina terenul este necesară calcularea informației de normală. Tehnica pe care o vom folosi se numește "aproximare prin diferențe finite" și utilizează informația vecinilor pixelului din care s-a interogat înălțimea vertexului curent. | ||
- | |||
- | * Se obține înălțimea de la poziția curentă, de la poziția din dreapta și de la cea de sus. | ||
- | |||
- | $$ | ||
- | height = texture2D(heightMap,vec2(u,v)).r \\ | ||
- | texelSize = vec2 (1.0/heightMapSize.x, 1.0/heightMapSize.y) \\ | ||
- | heightRight = texture2D(heightMap,vec2(u+texelSize.x,v)).r \\ | ||
- | heightUp = texture2D(heightMap,vec2(u,v+texelSize.y)).r | ||
- | $$ | ||
- | |||
- | * Se calculează diferențele pe $x$ și pe $z$. | ||
- | |||
- | $$ | ||
- | H_x = height - heightRight \\ | ||
- | H_z = height - heightUp \\ | ||
- | $$ | ||
- | |||
- | * Normala este reprezentată de vectorul unitate determinat de cele două diferențe pe $x$ și pe $z$. | ||
- | |||
- | $$ | ||
- | normal = normalize(vec3(H_x, 1, H_z)) | ||
- | $$ | ||
- | |||
- | <note tip> | ||
- | Deoarece diferențele dintre pixelul curent și vecini pot fi destul de mici, este recomandat să se folosească un factor de scalare pentru $H_x$ și $H_z$. | ||
- | </note> | ||
- | |||
- | Rezultatul după calcularea normalelor și adăugarea în scenă a unei lumini în centrul terenului: | ||
- | |||
- | {{ :egc:teme:2019:terrain3.png?nolink&600 |}} | ||
- | |||
- | Pentru adăugarea unei texturi de colorare a terenului (de exemplu pământ), se pot crea coordonate de textură suplimentare doar pentru aceasta sau se pot folosi coordonatele de la harta de înălțimi cu o scalare. Rezultatul final în urma aplicării luminii și a texturii se poate observa mai jos. | ||
- | |||
- | {{ :egc:teme:2019:terrain4.png?nolink&600 |}} | ||
- | |||
- | ====== Deformarea terenului ====== | ||
- | |||
- | ===== Buffer-ul hartii de inaltimi ===== | ||
- | |||
- | * Pentru a avea acces la buffer-ul de pixeli al imaginii este necesar să fie încărcată direct cu librăria [[https://github.com/nothings/stb|stb_image]]. Această librărie se află deja în framework și cu ajutorul ei se poate încărca întreaga matrice de pixeli a unui fișier. Se poate folosi direct imaginea incarcata in aceasta pagina. <code cpp>#include <stb/stb_image.h> | ||
- | |||
- | stbi_set_flip_vertically_on_load(true); | ||
- | heightPixels = stbi_load((textureLoc + "heightmap.png").c_str (), &width, &height, &channels, STBI_grey); | ||
- | </code> | ||
- | |||
- | * Buffer-ul ''heightPixels'' păstrează toată informația imaginii într-o zonă continuă de memorie în care prima dată se regăsește prima linie de pixeli (fiecare pixel are un singur canal de culoare), urmată de a doua linie ș.a.m.d. Pentru a incarca buffer-ul in memoria procesorului grafic se foloseste: <code cpp>glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, (void*)heightPixels); | ||
- | </code> | ||
- | |||
- | * Pentru a modifica textura, pur și simplu se modifică o zonă de pixeli din imagine, în interiorul acestui buffer și se reîncarcă buffer-ul în procesorul grafic cu directiva de mai sus. | ||
- | |||
- | ===== Notare (150p) ===== | ||
- | * Construcția terenului (50p) | ||
- | * Deformarea terenului (50p) | ||
- | * Camera third person + lansare proiectil (20p) | ||
- | * Deplasare proiectil + camera observatie (20p) | ||
- | * Lumini spot deasupra celor doua personaje (10p) | ||
- | |||
- | ===== Arhivarea proiectului ===== | ||
- | |||
- | <note> | ||
- | * În mod normal arhiva trebuie să conțină toate resursele necesare compilării și rulării | ||
- | * Înainte de a face arhiva asigurați-vă că ați dat clean la proiect | ||
- | * Click dreapta pe proiect în **Solution Explorer** -> **Clean Solution**, sau | ||
- | * Ștergeți folderul __**/Visual Studio/obj**__ | ||
- | * Ștergeți fișierul __**/Visual Studio/Framework_EGC.sdf**__ (în caz că există) | ||
- | * Ștergeți fișierul __**/Visual Studio/Framework_EGC.VC.db**__ (în caz că există) | ||
- | * Ștergeți folderul __**/.vs**__ (în caz că există) | ||
- | * Ștergeți folderul __**/x64**__ sau __**/x86**__ (în caz că există) | ||
- | * Executabilul final este generat în folderul __**/x86**__ sau __**/x64**__ la finalul link-editării în funcție de arhitectura aleasă la compilare (32/64 biți) | ||
- | * În cazul în care arhiva tot depășește limita de 20MB (nu ar trebui), puteți să ștergeți și folderul __**/libs**__ sau __**/Resources**__ întrucât se pot adăuga la testare. Nu este recomandat să faceți acest lucru întrucât îngreunează mult testarea în cazul în care versiunea curentă a bibliotecilor/resurselor diferă de versiunea utilizată la momentul scrierii temei. | ||
- | </note> | ||
- | |||
- | </hidden> |