This is an old revision of the document!
În cadrul temei 3 trebuie să implementați versiunea de Worms în 3D cu teren deformabil. În continuare este prezentat un demo cu toate funcționalitățile de bază.
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(textureUnit,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țimi 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. 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.
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\}$, asociate vertexului. Această valoare se poate asocia direct coordonatei $y$ a vertexului sau se poate scala pentru un impact mai mare al terenului.
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.
$$ 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 după calcularea normalelor și adăugarea în scenă a unei lumini în centrul terenului:
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.
#include <stb/stb_image.h> heightPixels = stbi_load((textureLoc + "heightmap.png").c_str (), &width, &height, &channels, STBI_grey);
heightPixels
păstrează toată informația imaginii într-o zonă continuă de memorie în care în prima parte se găsește prima linie de pixeli (fiecare pixel are un singur canal de culoare), urmată de a doua linie de pixeli ș.a.m.d. Pentru a încărca buffer-ul în memoria procesorului grafic se folosește: glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, (void*)heightPixels);
Jocul va fi multiplayer local în care pe rând fiecare jucător va prelua controlul a două personaje aflate în zone diferite ale terenului. Fiecare jucător va avea la dispoziție un singur proiectil pe tură. Acesta va avea o cameră third-person asupra personajului pentru a putea potrivi ținta. Odată decis, la apasărea butonului click stânga de la mouse, proiectilul este lansat și este urmărit de cameră fără ca jucătorul să mai aibă control. La impactul proiectilului cu terenul, acesta va lăsa în urmă un crater. La urmatoarea tură se schimbă personajul.