This is an old revision of the document!
Î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.
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.
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 și toate coordonatele $y = 0$. De asemenea, fiecărui vertex trebuie să i se asocieze o coordonată de textură, $\{u,v\} \in [0, 1]$, normalizată între limitele geometriei pe $x$ și pe $y$. În mod particular, geometria din imaginea de mai jos a fost generată cu $100$ de linii și $100$ de coloane, pe o suprafață de $5$x$5$ unități.
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. Rezultatul în urma desenării geometriei suport descrise anterior, cu textura de inălțimi de mai sus, pe care s-a aplicat un factor de scalare al inălțimilor de $2$ se poate observa mai jos.
Pentru a putea lumina terenul este necesară informația de normale. Tehnica pe care o vom folosi se numește “aproximare prin diferențe finite” și utilizeaza informația vecinilor pixelului din care s-a interogat înălțimea vertexului curent.
$$ 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 $$
$$ H_x = height - heightRight \\ H_z = height - heightUp \\ $$
$$ normal = normalize(vec3(H_x, 1, H_z)) $$
Rezultatul dupa calcularea normalelor si adaugarea in scena a unei lumini in centrul terenului:
Pentru adaugarea unei texturi de desenare a terenului (de exemplu pamant), se poate crea o coordonata de textura suplimentara doar pentru ea sau folosirea coordonatelor de la harta de inaltime cu o scalare. Rezultatul final in urma aplicarii luminii si a texturii se poate observa mai jos.
Pentru a avea acces la buffer-ul de pixeli al imaginii este necesar sa o incarcam cu o alta metoda:
#include <stb/stb_image.h> ... int width, height, chn; heightPixels = stbi_load((textureLoc + "heightmap.png").c_str (), &width, &height, &chn, 0); Texture2D* texture = new Texture2D(); texture->Create(heightPixels, width, height, chn); mapTextures["height"] = texture;
Buffer-ul heightPixels
pastreaza toata informatia imaginii ca zona continua de memorie in care prima data se gaseste prima linie de pixeli (fiecare pixel are chn
canale de culoare, bytes), urmata de a doua linie samd. Pentru a modifica textura, pur si simplu se modifica o zona de pixeli din imagine, in interiorul acestui buffer si se reincarca buffer-ul la procesorul grafic.
texture->UploadNewData(heightPixels);