160 likes | 301 Views
Programowanie gier komputerowych Tomasz Martyn. Wykład 6. Teksturowanie.
E N D
Programowanie gier komputerowychTomasz Martyn Wykład 6. Teksturowanie
W procesie rasteryzacji wartości przekazywane na wyjście shadera wierzchołków (np. wartości atrybutów) podlegają interpolacji – w wyniku rasteryzacji otrzymuje się fragmenty (tj. piksele wraz wartością głębi), którym przypisane są odpowiednie wartości po interpolacji. • W szczególności, tymi wartościami mogą być współrzędne tekstury (lub tekstur) przekazywane do potoku graficznego jako atrybuty wierzchołków (DirectX – wsp. UVW, OpenGL – wsp. STR) • Nominalne wartości współrzędnych tekstury należą do zakresu [0,1], sposób interpretowania wartości spoza tego zakresu zależy od parametrów adresowania tekstury • Przez teksturowanie będziemy rozumieli operację modyfikowania wartości koloru fragmentów przy użyciu wartości odczytanych z tekstury (lub kilku tekstur) za pomocą funkcji filtrowania tekstury w miejscu określonym przez współrzędne tekstury (lub tekstur) skojarzone z danym fragmentem w procesie rasteryzacji. • W celu teksturowania w grach wykorzystuje się najczęściej tekstury 2D, a także tekstury kubiczne. Informacje podstawowe
W grach, w celu teksturowania należy zwykle wykonać następujące operacje (niekoniecznie w podanej kolejności): utworzenie bazowego obrazu tekstury wygenerowanie sekwencji mipmap utworzenie obiektu tekstury (np. poprzez wczytanie odpowiednich danych z pliku) w odpowiedniej pamięci (zwykle Video RAM) zdefiniowanie odwzorowania geometriatekstura poprzez przypisanie wierzchołkom odpowiednich współrzędnych z układu współrzędnych tekstury zdefiniowanie parametrów filtrowania tekstury zdefiniowanie parametrów trybu adresowania (zawijania) tekstury zdefiniowanie parametrów mieszania tekstury z bieżącym kolorem fragmentu oraz ew. parametrów mieszania tekstur pochodzących z różnych jednostek teksturowania w przypadku multiteksturowania przypisanie tekstur do jednostek teksturowania i... renderowanie Podstawowe operacje związane z teksturowaniem stosowane w grach
Tekstury statyczne, to jest te, których zawartość nie ulega zmianie podczas działania gry, wraz sekwencją mipmap tworzone są na ogół off-line w fazie projektowania gry (np. pliki DDS). Tekstury dynamiczne generowane są najczęściej przy użyciu techniki renderingu do tekstury (np. mapy cieni, mapy dla dynamicznego otoczenia), zaś odpowiednia sekwencja mipmap – przez kartę graficzną (o ile posiada taką możliwość). Tworzenie zawartości tekstury
Odwzorowanie geometriatekstura określa w sposób jednoznaczny w jaki (najczęściej dwuwymiarowa) tekstura jest nakładana na powierzchnię obiektu geometrycznego (zwykle siatkę trójkątów) opisanego przez ciąg wierzchołków. • W przypadku standardowego teksturowania przyporządkowanie to tworzone jest na ogół w fazie projektowania gry, podczas tworzenia modelu przy użyciu dedykowanej aplikacji graficznej (3D Studio, Blender,...). • Jednakże przyporządkowanie to może być później dynamicznie modyfikowane w trakcie działania gry – np. efekty bazujące na tzw. animacji współrzędnych tekstury). • Nadto, w wielu efektach (mniej lub bardziej) specjalnych, przyporządkowanie współrzędnych tekstury do wierzchołków/fragmentów może odbywać się dynamicznie podczas wykonywania programu (np. projekcja tekstury, mapowanie cieni, mapowanie otoczenia, ...) Tworzenie odwzorowania tekstury na geometrię
API DirectX udostępnia wygodne w użyciu funkcje utworzenia obiektu (interfejsu) tekstury na podstawie danych obrazu tekstury umieszczonych w pliku (obsługiwanych jest wiele formatów graficznych, w tym dds, jpg, bmp, png, tga). Utworzenie obiektu tekstury (1): DirectX W przypadku, gdy plik nie zawiera obrazów mipmap, obie funkcje generują odpowiednią sekwencję (wersja uproszczona - pełną sekwencję, wersja rozszerzona – w podanym zakresie MipLevels). (D3DX 10 i 11 analogicznie przy wykorzystaniu funkcji D3D1*CreateShaderResourceViewFromFile)
W OpenGL obsługa wczytywania danych obrazu tekstury z pliku przerzucona jest na programistę. Po wczytaniu danych obrazu do pamięci RAM, obiekt tekstury w pamięci Video RAM tworzy się przy wykorzystaniu funkcji glGenTextures i glBindTexture łącznie z funkcją glTexImage*D. W przypadku, gdy plik nie zawiera mipmap, sekwencję taką można wygenerować i załadować do obiektu automatycznie wykorzystując funkcje gluBuild*DMipmaps (lub gluBuild*DMipmapsLevels - wersja rozszerzona). , file Utworzenie obiektu tekstury (2): OpenGL
Parametry filtrowania tekstury definiują sposób wyznaczania wartości określonych współrzędnymi tekstury na podstawie sekwencji mipmapi/lub pojedynczej tekstury. • filtr pomniejszający jest stosowany gdy powierzchnia teksela (po zrzutowaniu na ekran) jest mniejsza od powierzchni piksela • najbliższy (teksel) – wybierana jest wartość przechowywana w tekselu, który znajduje się najbliżej piksela • liniowy – wartość wyznaczana jest poprzez dwuliniową interpolację wartości tekseli w otoczeniu piksela • anizotropowy – kosztowny obliczeniowo, redukuje artefakty w odwzorowaniu tekstury powstające, gdy kąt między normalną do trójkąta i kierunkiem „patrzenia” kamery jest duży • filtr powiększający jest stosowany gdy powierzchnia teksela jest większa od powierzchni piksela (rodzaje jak w filtrze pomniejszającym) • filtrowanie mipmap • najbliższa (mipmapa) – wybierana jest mipmapa o powierzchni tekseli najbliższej powierzchni pikseli i następnie stosowane jest albo filtrowanie pomniejszające, albo powiększające • liniowe – wybierane są dwie sąsiednie mipmapy o powierzchniach tekseli najbliższych powierzchni piksela, następnie stosowane są do nich, odpowiednio, filtr powiększający i pomniejszający; wartość finalna wyznaczana jest poprzez liniową interpolację wartości z poprzedniego kroku Filtrowanie tekstur (1)
W API DirectX parametry filtrowania tekstury należą do stanu tzw. samplera, który można utożsamiać z jednostką teksturującą o zadanym numerze. W potoku D3DX 9 (stałym i programowalnym) oraz programowalnym D3DX 10 i 11 parametry filtrowania tekstury można zdefiniować przy użyciu metody SetSamplerState interfejsu urządzenia (D3DX 10 i 11 metody CreateSamplerStatei PSSetSamplers), np: W potokach programowalnych D3DX 9 – 11parametry filtrowania samplera można również określić bezpośrednio w kodzie shaderów poprzez zdefiniowanie obiektu stanu samplera, np: Filtrowanie tekstur (2): DirectX
W OpenGL parametry filtrowania tekstury określa się przy użyciu funkcji glTexParameteri wywoływanej z odpowiednimi argumentami, na ogół, w czasie tworzenia obiektu tekstury (wówczas parametry filtrowania zapamiętywane są w obiekcie tekstury; jednakże można je później modyfikować dla danej tekstury wywołując funkcje glTexParameteri po „dowiązaniu” tej tekstury przy użyciu funkcji glBindTexture): w kontekście aktywnej jednostki teksturującej (funkcja glActiveTexture) Począwszy od wersji 3.3 można używać w tym celu funkcji glSamplerParameter. Filtrowanie tekstur (3): OpenGL
Parametry adresowania (zawijania) tekstury określają sposób odwołania do zawartości tekstury w przypadku, gdy wartości współrzędnych tekstury wykraczają poza nominalny zakres [0, 1]. Adresowanie tekstury (1)
W DirectX parametry adresowania tekstury należą stanu samplera (podobnie jak parametry filtrowania). W potoku D3DX 9 (stałym i programowalnym) oraz programowalnym D3DX 10 i 11 parametry adresowania tekstury (oddzielnie dla każdej współrzędnej tekstury) można zdefiniować przy użyciu metody SetSamplerState interfejsu urządzenia (D3DX 10 i 11 metody CreateSamplerState i PSSetSamplers), np.: W potokach programowalnych (D3DX 9 – 11) parametry te można określić bezpośrednio w kodzie shaderóww obiekcie stanu samplera, np: Podobnie, w OpenGL używa się w tym celu funkcji glTexPameteri, np: wywoływanej w kontekście aktywnej jednostki teksturującej (funkcja glActiveTexture) Adresowanie tekstury (2)
Operacje mieszania w teksturowaniu określają sposób modyfikacji koloru bieżącego fragmentu przy użyciu wartości otrzymanej z tekstury przynależnej do i-tej jednostki teksturującej. tekstura bieżący kolor fragmentu W stałym potoku graficznym operacje mieszania definiowane są odrębnie dla każdej jednostki teksturującej, zaś mieszanie barwy fragmentu z wartościami pobranymi z tekstur następuje w sposób sekwencyjny. W stałym potoku DirectX 9 operacje te definiuje się przy wykorzystaniu metody SetTextureStageState interfejsu urządzenia oddzielnie dla koloru RGB i kanału , np: W stałym potoku OpenGL służy do tego funkcja środowiska tekstur glTexEnv*, wykorzystanej w kontekście aktywnej jednostki teksturującej (glActiveTexture) Operacje mieszania tekstur W potokach programowalnych operację mieszania tekstur definiuje się pisząc swój własny kod shadera pikseli (powyższe funkcje w API bez potoku stałego zostały wycofane).
W OpenGL (we wszystkich wersjach) przypisanie obiektu tekstury do jednostki teksturowania dokonywane jest przy użyciu funkcji glBindTexture z nazwą utworzonego obiektu tekstury jako argumentem, wywołanej w kontekście aktywnej jednostki teksturującej (glActiveTexture). (W celu dokonywania teksturowania należy je również uaktywnić funkcją glEnable). W stałym potoku (ale również programowalnym) DirectX 9 obiekt (interfejs) tekstury można dowiązać do jednostki teksturującej za pomocą metody SetTexture(NoStage, pTexture) interfejsu urządzenia. W programowalnym potoku DirectX 9 dowiązanie obiektu tekstury następuje poprzez jego dowiązanie do odpowiedniej zmiennej reprezentującej teksturę w shaderze pikseli przy użyciu metody interfejsu efektu (HLSL) SetTexture(”uchwyt_zmiennej”, pTexture). W podobny sposób dowiązanie tekstury do shadera pikseli następuje w potokach D3DX10 i D3DX11. Przypisanie tekstury do jednostki teksturowania
W DirectX interfejsy reprezentujące tekstury usuwa się poprzez wywołanie standardowej metody dla obiektów COM, to jest metody Releaseinterfejsu tekstury. W OpenGL obiekty tekstur usuwa się przy użyciu funkcji glDeleteTextures. Usuwanie obiektów tekstur
Podobnie jak w przypadku buforów wierzchołków/indeksów (por. wnioski do Wykładu 5), dla potrzeb wieloplatformowego silnika graficznego należy: stworzyć, niezależne od API graficznego, klasy (być może szablonowe) reprezentujące obiekty tekstur i samplerów, w których metody interfejsu obudowują implementacje stosowane w konkretnych API graficznych same zaś implementacje dla konkretnego API należy dostarczyć w pliku implementacyjnym Wnioski