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 suprafata de baleiere descrisa de functia:
$$ f(x,z) = y $$
Datorita constructiei, o astfel de suprafata poate fi determinata direct de continutul unei texturi in urmatorul mod:
$$ f(x,z) = texture2D(unitTexture,vec2 (u,v)).r $$
unde $\{u, v\}$ reprezinta coordonatele de textura asociate coordonatelor spatiale $\{x,z\}$.
Aceste tipuri de texturi care descriu suprafete de baleiere se numesc harti de inaltime sau height maps. Ele contin in fiecare pixel o singura informatie in $[0,255]$ (normalizat $[0,1]$), pe un singur canal, ce reprezinta inaltimea zonei acoperite de pixelul respectiv. Un astfel de exemplu de textura se poate vedea mai jos.
Pentru a putea crea o suprafata definita de inaltimea data de textura este necesara o geometrie suport care sa cuprinda toate coordonatele $\{x,z\}$ finale si toate coordonatele y egale cu 0. De asemenea, fiecarui vertex trebuie sa i se asocieze o coordonata de textura, $\{u,v\} \in [0, 1]$, normalizata intre limitele geometriei pe x si pe y. In mod particular, geometria din imaginea de mai jos a fost generata cu 100 de linii si 100 de coloane, pe o suprafata de 5×5 unitati.
Geometria suport se deseneaza cu un shader special, care la pasul de vertex shader acceseaza textura in care sunt salvate inaltimile. Se obtine valoarea culoarea de la coordonatele $\{u,v\}$ asociate si se obtine o valoare in $[0,1]$. Aceasta valoare reprezinta inaltimea, coordonata y a vertexului, care se poate scala, dupa plac. O desenare a geometriei generate anterior cu inaltimile obtinute din textura de mai sus si cu factorul de scalare al inaltimii egal cu 2 va avea rezultatul din imaginea de mai jos.
Pentru a putea lumina intreaga suprafata este necesara informatia de normale. Exista diferite metode pentru a extrage normala la suprafata a unei geometrii generate pe baza unei functii, dar pentru simplitate vom folosi o metoda denumita calcul de diferente finite, care aproximeaza numeric normala.
Obtinem inaltimea de la pozitia curenta, de la pozitia din dreapta si din fata (pe axa z).
$$ height = f(x,z) \\ heightRight = f(x+1,z) \\ heightUp = f(x,z+1) $$
Calculam diferentele pe x si pe z.
$$ H_x = height - heightRight \\ H_z = height - heightUp \\ $$
Normala va fi vectorul normalizat care contine cele doua diferente pe x si pe z.
$$ normal = normalize(vec3(H_x, 2, H_z)) $$
Deoarece diferentele dintre height si vecini pot fi destul de mici, este recomandat sa inmultiti H_x si H_y cu un factor de scalare pentru a obtine normalele in mod coerent. Rezultatul dupa calcularea lor si adaugarea unei lumini punctiforme in centrul terenului poate fi observat in imaginea de mai jos.
Pentru a adauga o textura de “pamant” pe teren se poate crea o noua coordonata de textura sau se poate folosi o scalare a coordonatelor de textura folosite pentru harta de inaltimi impreuna cu parametrul GL_REPEAT
de impachetare al texturii.
$$ (u_2,v_2) = (u,v) * 20 $$
Rezultatul final in urma aplicarii luminii si a texturii de “pamant” se poate observa in imaginea de mai jos.
Pe lângă obstacole sau combustibil, pot să existe și alte obiecte specifice în scenă ce aduc anumite beneficii/dezavantaje (de exemplu, o sferă galbenă poate aduce o viață în plus sau un cub verde face avionul invincibil pentru o perioadă de timp, sau poate trage proiectile pentru distrugerea obstacolelor etc.).