240 likes | 434 Views
Programowanie gier komputerowych Tomasz Martyn. Wykład 5. Geometria Teren. Z ogólnego, niezależnego od implementacji punktu widzenia, dane stanowiące opis geometrii modelu zorganizowane są w skończoną sekwencję (lub grupę sekwencji ) punktów-wierzchołków ( vertices ).
E N D
Programowanie gier komputerowychTomasz Martyn Wykład 5. Geometria Teren
Z ogólnego, niezależnego od implementacji punktu widzenia, dane stanowiące opis geometrii modelu zorganizowane są w skończoną sekwencję (lub grupę sekwencji) punktów-wierzchołków (vertices). Rendering modelu odbywa się poprzez skierowanie do potoku graficznego sekwencji wierzchołków reprezentujących model. W aplikacjach graficznych czasu rzeczywistego (np. grach) dąży się do przekazywania danych geometrycznych do potoku graficznego w jak największych paczkach (batches), przy użyciu jak najmniejszej liczby wywołań funkcji API. W szczególności, (na ogół) NIE wykorzystuje się w tym celu – implementowanego we wcześniejszych (poniżej wersji 3.0) wersjach OpenGLa – trybu bezpośredniego: Informacje ogólne
Wierzchołki są przede wszystkim nośnikami informacji o położeniu tworzących model punktów (zwykle rozważanych właśnie jako wierzchołki siatki trójkątów tworzących powierzchnię modelu, często w układzie współrzędnych modelu). Jednakże, w odróżnieniu od wierzchołków „matematycznych”, oprócz położenia, wierzchołki „graficzne” zawierają zwykle dodatkową informację wykorzystywaną przez potok graficzny – np. kolor punktu, wektor normalny w punkcie, współrzędne tekstur definiujące odwzorowanie tekstury (lub tekstur) na powierzchnię modelu, etc. Składowe tworzące wierzchołki graficzne określane są jako atrybuty wierzchołków (vertexattributes). Każdy z wierzchołków danej sekwencji tworzącej model (lub jego część) zdefiniowany jest przez te same atrybuty, np.: Atrybuty wierzchołków
Sekwencja wierzchołków może być zorganizowana w pamięci (RAM, Video RAM, dysk twardy,...) na kilka sposobów: • wszystkie dane (atrybuty) wierzchołków sekwencji umiejscowione są w jednym buforze (strumieniu) wierzchołków: • dane każdego z rodzajów atrybutów wierzchołków znajdują się w odrębnym buforze (strumieniu): • reprezentacje pośrednie (dane poszczególnych atrybutów rozdzielone są pomiędzy 2 lub więcej buforów) • Sposób zorganizowania ma znaczenie m.in. dla wydajności operacji odczytu i zapisu danych z/do bufora wierzchołków dokonywanych przez CPU, gdy bufor przechowywany jest w pamięci karty graficznej (Video RAM). Organizacja w pamięci
W siatkach trójkątów większość wierzchołków jest współdzielonych przez 2 lub więcej trójkątów: • Reprezentowanie siatki trójkątów wyłącznie za pomocą ciągu trójek wierzchołków definiujących trójkąty skutkowałoby zatem (często wielokrotnym) powielaniem wierzchołków (i ich atrybutów). • To, z kolei, pociągałoby nie tylko marnowanie zasobów pamięciowych (w szczególności VRAM), ale także marnowanie „przepustowości” łącza podczas przesyłania wierzchołków pomiędzy CPU i GPU. • W celu poradzenia sobie z problemem redundancji wierzchołków wykorzystuje się bufory indeksów: Indeksy wierzchołków
Przekazywane do potoku graficznego sekwencje danych, które reprezentują wartości atrybutów kolejnych wierzchołków modelu, są strumieniami bajtów. • Deklaracja wierzchołka (vertexdeclaration, vertexlayout) jest wymaganym przez dane API, formalnym sposobem poinformowanie potoku o semantyceposzczególnych wartości atrybutów, ich typie oraz ich organizacji. • W zależności od API, deklaracja wierzchołka dokonywana jest: • albo w sposób jawny przy użyciu odpowiednich funkcji API dedykowanych temu celowi, • albo niejawniew trakcie formatowania operacji przesłania atrybutów werteksów do karty graficznej. • W DirectX mamy do czynienia z jawnym sposobem deklarowania wierzchołka, podczas gdy w OpenGLdeklaracja wierzchołka uwikłana jest w przygotowanie procesu przesłania danych do karty graficznej. Deklaracja wierzchołka (1)
W D3DX 9 (w D3DX 10 i 11 analogicznie) każdy z atrybutów opisany jest strukturą: • Np. deklaracja wierzchołka może mieć postać: • Utworzenie interfejsu deklaracji wierzchołka oraz poinformowanie potoku o aktualnej deklaracji odbywa się poprzez wywołanie metod: Deklaracja wierzchołka (2): DirectX
W OpenGL organizacja atrybutów wierzchołków deklarowana jest podczas przygotowywania procesu przesyłania danych do karty graficznej. W wersji OpenGL 3.0 (i wcześniejszych) oraz OpenGL ES 1.x wykorzystuje się w tym celu m.in. funkcje glVertexPointer, glColorPointer, glNormalPointer, glTexCoordPointer , np.: łącznie z funkcjami glEnableClientState(Glenumarray) aktywującymi odpowiednie tablice (strumienie) atrybutów, np: Począwszy od wersji OpenGL 3.1 oraz OpenGL ES 2.0, w których usunięto stały potok graficzny, odpowiednia deklaracja atrybutów wierzchołków odbywa przy użyciu funkcji glVertexAttribPointer(i następnie funkcji kojarzących dany atrybut z odpowiednią zmienną w shaderze wierzchołków – wykłady 8-9) Deklaracja wierzchołka (3): OpenGL
OpenGL w wersjach 1.1−2.x (OpenGL ES 1.x) udostępnia funkcjonalność indeksowanych tablic wierzchołków: • gdzie • przesyła strumień wierzchołków do potoku graficznego. • Wadą tablic wierzchołków jest to, że są przechowywane po stronie CPU i w celu renderingu za każdym razem muszą być przesyłane do karty graficznej. Indeksowane tablice wierzchołków OpenGL
Bufory wierzchołków i indeksów stosowane w DirectX nie posiadają wskazanej wady tablic wierzchołków OpenGL, bowiem bufory te mogą egzystować bezpośrednio w pamięci VRAM karty graficznej. • W D3DX 9 (podobnie w D3DX 10 i 11) bufory wierzchołków tworzy się za pomocą metody: • Analogicznie, bufory indeksów tworzy się przy wykorzystaniu metody CreateIndexBuffer o podobnych parametrach. • W celu wypełnienia bufora danymi (ew. odczytu danych) należy otrzymać do niego wskaźnik wywołując metodę Lock (odpowiednio Map w D3DX 10 i 11), a następnie po wypełnieniu bufor odblokować wywołując metodę Unlock (odpowiednio Unmap w D3DX 10 i 11). Bufory wierzchołków DirectX (1)Inicjalizacja
W celu renderowania geometrii: • bufory wierzchołków należy skojarzyć z odpowiednimi strumieniami określonymi w deklaracji wierzchołka (w D3X9 metoda SetStreamSource, w D3DX 10 i 11 metoda IASetVertexBuffers) • skojarzyć z potokiem bufor indeksów (w D3DX 9 metoda SetIndices, w D3DX 10 i 11 SetIndexBuffer) • poinformować potok o bieżącej deklaracji wierzchołka (w D3X9 metoda SetVertexDeclaration, w D3DX 10 i 11 IASetInputLayout) • wywołać polecenie przesłania wierzchołków do potoku graficznego (w D3DX9 metoda DrawIndexedPrimitive, w D3DX 10 i 11 DrawIndexed poprzedzona metodą IASetPrimitiveTopology) Bufory wierzchołków DirectX (2)Renderowanie
W celu realizowania funkcjonalności analogicznej do buforów wierzchołków DirectX, w OpenGL w wersji 1.5 wprowadzono obiekty buforowe (objectbuffers) umożliwiające przechowywanie tablic wierzchołków i indeksów bezpośrednio w pamięci karty graficznej (Video RAM). • tworzenie obiektu buforowego indeksowanej tablicy wierzchołków • w celu zmiany zawartości (ew. odczytu) utworzonego obiektu buforowego należy (podobnie jak w DirectX) otrzymać do niego wskaźnik (funkcja glMapBuffer), a następnie bufor odblokować (glUnmapBuffer). Funkcja glBufferSubData pozwala zapisać dane do dowiązanego bufora bez odwzorowywania go w RAM. Obiekty buforowe w OpenGL (1)Inicjalizacja
Począwszy od wersji OpenGL 3.0 (OpenGL ES 2.0) zrezygnowano z obiektów buforowych tablic wierzchołków znanych z poprzednich wersji i w ich miejsce wprowadzono po prostu obiekty buforów wierzchołków (vertexbufferobject - VBO). Obiekty te używa się w niemalże identyczny sposób. Jedna z głównych różnic to ta, że w miejsce wywołań wycofanych funkcji: glEnableClientState i deklaracji atrybutów wierzchołka glVertexPointer, glNormalPointer, etc., wykorzystuje się funkcję ogólną glVertexAttribPointer(oraz m.in. glEnableVertexAttribArray). Dodatkowo wprowadzono nowy typ obiektu wspomagającego wykorzystywanie VBO, noszącego nazwę VertexArray Object (VAO). Obiekty buforowe w OpenGL (2)Renderowanie
W przypadku wieloplatformowego silnika graficznego należy: stworzyć, niezależną od API graficznego, klasę (być może szablonową) reprezentujący bufory wierzchołków/indeksów i działania na nich, której metody interfejsu obudowują implementacje stosowane w konkretnych API graficznych same zaś implementacje dla danego API należy dostarczyć w pliku implementacyjnym Nadto: mając na uwadze wydajność kodu, należy starać się unikać stosowania funkcji wirtualnych (szczególnie wywoływania takich funkcji w wykonywanych wielokrotnie pętlach); koszt wywołania funkcji wirtualnej jest często dużo większy od wywołania zwykłej funkcji z powodu zjawiska „chybiania w cache” (cache misses) należy pamiętać o tym, że pomimo, iż na danej platformie mogą działać różne API graficzne (np. na PC), to jednak wersja releasegry będzie wykorzystywała tylko jedno z nich (dlatego m.in. nie ma sensu aby kod wynikowy zawierał implementacje dla API niewykorzystywanych) Wnioski
zbuduj drzewo czwórkowe na podstawie prostopadłościanów AABB siatek składowych dokonaj wstępnej selekcji siatek składowych względem bieżącej bryły widzenia wykorzystując utworzoną hierarchię Teren (5)Selekcja siatek składowych
Wędrowanie po terenie (1)Przekształcenie do współrzędnych siatki
Wędrowanie po terenie (3)Przemieszczanie się wzdłuż stycznej