Wyświetlanie terenu Clipmapy geometrii
Rendering terenu Łatwy do zaimplementowania Darmowe zestawy danych Liczne zastosowania: Wizualizacje geograficzne Symulatory Gry
Ogromne ilości danych Gry Od 2x2 do 40x40 km Ograniczona pamięć (konsole, karty graficzne) <150mb 8192x8192 pixeli Potrzebna duża dokładność Dane z dokładnością do metrów
Ogromne ilości danych Wizualizacje, DEM, planety: Rozdzielczość 90m to także za mało Wielkość danych sięga gigabajtów Strumieniowanie z dysku, z internetu
Level of detail Algorytmy LOD dla terenu: Nieregularne siatki (TIN) View-dependent Regularne: Różne sposoby podziału Chunked LOD Tiles
Współczesne GPU GPU coraz szybsze GPU<->CPU wolne! Najlepiej nie blokować zasobów GPU Mapa wysokości tekstura Vertex Texture Fetch Instancing, DX10...
Clipmapping 'Rozszerzenie' mipmap Przechowujemy L poziomów (tekstury) rozmiaru n x n Rysujemy L 'okien' wokół obserwatora, każde 2x większe Dodatkowo poziom L-1 jako zwykłą siatkę Mapujemy wysokości w VS Uaktualniamy tekstury podczas ruchu
Uwagi Nie przesuwamy poziomów płynnie DX9 nie ma filtrowania tekstur w VS Wierzchołki odpowiadają 1:1 tekselom Inaczej teren 'pływa' Musimy odpowiednio podzielić 'okna' Oraz dbać o wysokości na granicach poziomów (zapobieganie T-junctions)
Implementacja-geometria 'Okno' dzielimy na części Rozmiar n = 2 k-1 Wystarczy przechować 3 VB Stałe wymagania pamięciowe Poziomy dopasowane do rozmiarów tekstur m= n 1 4
Mapy wysokości Jedna tekstura dla każdego poziomu (R32 lub R16) Za każdym razem uaktualniamy tylko część poziomów Dodatkowo przechowujemy 2x wieksza mape normalnych (A8R8G8B8) Obliczona na GPU (upsampling mapy wysokości)
Rendering Możemy ominąć najdokładniejsze poziomy 'Okna' sa przesunięte względem poprzednich poziomów Frustum Culling podział 'okien' pozwala wiele wykluczyć
Rendering Vertex Shader T-junctions musimy odpowiednio przesuwać wierzchołki graniczne Potrzebujemy wysokość na niższym poziomie Obliczyć współczynnik α do dodawania wysokości, np. f = ((abs(leveluv.xy-0.5f)*2.0f-w)/(1.0f-w)) alpha = max(0.0f,0.5f*max(f.x,f.y)) H = αhcurr +(1-α)Hcoarser Odpowiednio rozmieszczamy bloki oraz wyliczamy UV względem poziomu oraz świata
Rendering Pixel Shader Mapa normalnych 2x wieksza Inaczej wynik jest rozmyty Trzeba uważać na granicach tak jak z wysokościami Mapa normalnych: A8R8G8B8 zapisane jako (N x,n z,n cx,n cz) Ncz, Ncz normalne z niższego poziomu Zakładamy Ny=Ncy = 1
Instancing Musimy minimalizować wywołania sterownika (np. DrawPrimitive) oraz zmiany stanu DX9 konieczne OpenGL, DX10 wciąż bardzo ważne Jedno wywołanie Draw może rysować obiekt wiele razy SV_InstanceID w PS lub VS indeksuje tablice z danymi Jeden poziom za pomocą 3 wywołań Draw DX10 pozwala na jeszcze więcej!
Uaktualnianie poziomów Uaktualniamy poziom tylko jeśli przesuwa się jego 'okno' Render-To-Texture Najpierw uaktualniamy mapę wysokości, na jej podstawie mapę normalnych 'toroidal access' nie musimy renderować całej mapy możemy tylko część o kształcie krzyża Musimy przesunąć współrzędne tekstur podczas wyświetlania (texture address = WRAP)
Kompresja danych Tworzymy pełną piramidę mipmap T 1,...,T m dla oryginalnych danych (Tm najdokładniejsza) Obliczamy U(Ti) interpolujemy wysokości z mniej dokładnych map (schemat opisany w [1] oraz [2], kod w HLSL na płycie do [2]) Obliczamy Ri=Ti-U(Ti-1) pozostałości (ang. residuals) Przechowujemy tylko najmniej dokładne poziomy Oraz skompresowaną mapę pozostałości Kompresja stratna błędy mogą się kumulować (patrz [1]) Kompresja musi pozwalać na ROI (region of interest) Dokładne informacje w [1] i [2]
Uaktualnianie wysokości Możemy odtworzyć wysokości ze skompresowanych danych Z dysku wczytujemy tylko najniższy poziom Pozostałe interpolujemy i dodajemy pozostałości Zamiast tego możemy dodać szum obliczony na GPU Nieograniczona dokładność Obliczamy dwie wysokości dokładną oraz z niższego poziomu w danym punkcie Np. H = Hcurr + (Hcoarser +256)/512 To samo robimy dla normalnych
Optymalizacje i rozszerzenia Obliczanie normalnych w VS Wykorzystywanie tylko dwóch map wysokości DX10: Texture Arrays rysowanie wszystkich poziomów za pomocą 3 wywołań Draw() Terrain Rendering using Spherical Clipmaps Proceduralne generowanie terenu
Podsumowanie Stosunkowo prosty pomysł Nie taki prosty w implementacji Świetny dla dużych zestawów danych Pozwala na dużą kompresję, przy niewielkiej utracie jakości Równomiernie rozkłada wczytywanie nowych danych na wiele klatek Dla mniejszych terenów (np. gry) możemy znaleźć bardziej odpowiednie algorytmy Nie adaptuje się do cech terenu zazwyczaj jednak nie powinno to być problemem
Dodatkowe informacje [1] Geometry clipmaps: Terrain rendering using nested regular grids, F. Losasso, H. Hoppe. http://research.microsoft.com/~hoppe/proj/geomclipmap/ [2] Terrain Rendering Using GPU-Based Geometry Clipmaps, GPUGems2, Arul Asirvatham and Hugues Hoppe (Microsoft Research) http://http.developer.nvidia.com/gpugems2/gpugems2_chapter02.html [3] http://vterrain.org/ [4] Terrain Rendering Using Geometry Clipmaps, Nick Brettell http://www.cosc.canterbury.ac.nz/research/reports/honsreps/2005/hons_0502.pdf [5] http://gamedev.net/