Autor Wątek: Occlusion Culling  (Przeczytany 1421 razy)

Offline Trix

  • Użytkownik

# Sierpień 20, 2016, 23:36:40
W jaki sposób wykonuje się w OGL Occlusion Culling?
A może wczesny test głębi to jest Occlusion Culling?

Frustrum Culling już zaprogramowałem (opartej na sprzężeniu zwrotnemu).

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Mergul

  • Użytkownik

  • +2
# Sierpień 21, 2016, 07:32:28
Sposobów jest sporo. Jeden sposób to occulision query, rysujesz obiekty z prostymi shaderami i sprawdzasz czy wyrysowal sie jakis fragment. Ale jest to technika dosyć niewydajna ze względu na to, że tracisz sporo na transferze CPU - GPU.
Raczej stosuje sie testy przyslaniania na CPU. Jednym z rozwiązań dla zamkniętych pomieszczeń są portale, nie są jednak dziś zbyt często wykorzystywane.  Najczęściej wykorzystuje sie rasteryzacje na CPU (CryEngine, BattleField). Robisz to tak: tworzysz wydajny algorytm rasteryzacji samej glębi, rysujesz do niego uproszczone modele, testujesz obiekty rysujac ich bryły otaczajace. Algorytm najczęściej optymalizuje sie pod SIMD i wielowątkowość. Na warsztacie mam filmik z occlusion cullingu w moim silniku, uzywam rasteryzacji na CPU, to możesz zobaczyc jak to mniej więcej wygląda.
Innym częstl sykorzystywanym sposobem jest Umbra3, jest to płatny silnik do occlusion cullingu oparty na rasteryzacji CPU, z tą różnica, że dla statycznej sceny budowana jest siatka voxeli, i tworzone są portale. A dla obiektów dynamicznych, standardowa rasteryzacja.
Jest jeszcze dużo innych rozwiązań, ale są raczej mniej wydajne i rzadziej wykorzystywane.

Offline Trix

  • Użytkownik

# Sierpień 21, 2016, 11:43:04
Rasteryzacja na CPU, czyli stworzę BoundingBox dla chunk'ów lub całych obiektów ->
wyłączę rasteryzację kolorów:
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); ->
narysuję obiekt na prostych shaderach ->
sprawdzę za pomocą zapytań czy narysował się jakiś fragment ->
i jeśli tak, to narysuję dany chunk lub cały obiekt, o to chodziło?

W takim razie Fustrum Culling do wyrzucenia, bo zostanie zrealizowany również w tym procesie?

Offline Mergul

  • Użytkownik

  • +3
# Sierpień 21, 2016, 12:39:44
To jest na GPU. Czyli ten mniej wydajny :D
Na CPU to znaczy ze piszesz rasteryzacje na procesorze. Wgl. nie korzystasz z OGL-a do tego. Piszesz generowanie trójkątów z wierzchołków i rzutowanie ich na tablice 2D i wypełniasz tą tablice głębią :D

Frustum Culling jak najbardziej potrzebny, frustum culling jest generalnie duuużo szybszy i pozwala na odrzucenie szybko obiektów których nie warto ani testować occlusion culling-iem, ani wysyłac do karty.

Ogólnie to tak. Obietky trzymasz np. w Octree. Robisz frustum culling lecąc po Octree. Czyli testujesz tez dzieci drzewa (dla wydajności algorytmu), a tylko jeżeli dziecko przejdzie pozytywnie test to testujesz bryłę otaczającą (np. aabb). Tworzysz tablice obiektów, które przeszły ten test. Jeżeli masz zamiar wykonać test przysłaniania, to grupujesz obiekty na t które przysłaniają (tylko większe obiekty, nie warto rysować jako obiekt przysłaniający np. miotły), obiekty które mogą być przysłonięte (jeżeli byś testował każdy możliwy obiekt to nie dałoby rady, bo obiektów jest zbyt dużo), i np. grupy obiektów (jak masz małe obiekty to grupujesz je po kilka i testujesz wszystkie razem). Rysujesz ręcznie do tablicy w ramie trójkąty obiektów przysłaniających, później przeliczasz aabb obiektów testując je z głębią zapisaną w tablicy. Te które przeszły grupujesz po materiałach (coby jak najmniej zmieniać shadery, tekstury, vbo itp.), a następnie albo po odległości, żeby te z przodu przysłaniały te z tyłu (mniej fragmentów do liczenia, wierzchołki dalej musza być przeliczane),  albo robisz z prepass, czyli rysujesz wszystkie obiekty z prostym shaderem bez koloru, żeby zapełnić bufor głębi.
Głównym zadaniem Frustum i Occlusion Cullingu jest to żeby nie wysyłać zbędnych (niewidocznych) obiektów na karte graficzną, i żeby karta nie musiała przeliczać wierzchołków obiektów, których i tak nie widać :-)

Offline albireo

  • Użytkownik

# Sierpień 22, 2016, 07:08:43
Sposobów jest sporo. Jeden sposób to occulision query, rysujesz obiekty z prostymi shaderami i sprawdzasz czy wyrysowal sie jakis fragment. Ale jest to technika dosyć niewydajna ze względu na to, że tracisz sporo na transferze CPU - GPU.
Jak się sprawdza wyniki occlusion query na CPU to rzeczywiście może być niewydajna, ale można użyć conditional rendering (glBeginConditionalRender/glEndConditionalRender), wtedy sprawdzanie będzie po stronie GPU.

Offline Mergul

  • Użytkownik

  • +1
# Sierpień 22, 2016, 10:19:55
To i tak za wiele nie zmieni. Mało kto wykorzystuje dzisiaj tą technikę i raczej nie dlatego, że nie potrafi (wydaje mi się, że Crytek to całkiem niezła firma) :D
Co prawda gdy wchodził OGL4 to Nvidia udostępniła prezentacje o dużo wydajniejszym wykorzystaniu occlusion querys. Ale mimo wszystko, żeby mieć z czym testować to trzeba wcześniej narysować głębię (żeby mieć z czym testować), albo wykorzystać tą z poprzedniej klatki. Nigdy nie korzystałem z "conditional rendering", ale z tego co rozumiem to najpierw musisz wyrysować aabb obiektów, które testujesz, a później rysowac je w identycznej kolejności. Jeżeli się nie mylę, to:
-Musisz narysować wszystkie AABB obiektów do querys (tracisz na transferze na karte)
-Po drugie samo włączenie query spowalnia :D
-Następnie skoro obiekty są odrzucane na GPU to i tak musisz dla każdego obiektu ustawiać shadery, blending, tekstur, bufory itd. itp. (co jest jedną z bardziej kosztownych operacji i unika sie tego jak tylko się da)
-I na koniec, skoro testowane jest to na GPU to nie wiem czy da się grupowac mniejsze obiekty po kilka dla jednego AABB :D

Oczywiście, korzystając z querys da się zoptymalizować wydajność, jednak technika rasteryzacji na CPU okazała się być wydajniejsza i bardziej praktyczna.

Offline Trix

  • Użytkownik

# Sierpień 22, 2016, 12:49:22
Cytuj
Rysujesz ręcznie do tablicy w ramie trójkąty obiektów przysłaniających (...)
Jak takie coś zrobić?

Offline Mergul

  • Użytkownik

  • +2

Offline skmskm

  • Użytkownik

# Sierpień 22, 2016, 22:25:30
W większości gier nie trzeba budować zbyt skomplikowanego filtru obiektów, wystarczy zwykłe pudełko(łatwy  i szybki test). To zależy jak wielką mapę planujesz, dzisiejsze karty np.: Geforce 660Ti może rysować 1milionów trójkątów na klatkę bez żadnego problemu przy 30 klatkach na sekundę.
Oczywiście na kolizje proponuje octree(drzewo czwórkowe lub ósemkowe odpowiednio zoptymalizowane).

Offline Mergul

  • Użytkownik

  • +1
# Sierpień 23, 2016, 10:50:03
Nie mozna powiedzieć, że karta rysuje milion trójkątów. Ja zrobię instancing to moja karta (gtx 750Ti) narysuje ich płynnie nawet 27mln, jak postawię dużo pudełek, do tego z różnymi materiałami to narysuje może 500k i zarżne karte ;)
Jeżeli już został zaimplementowany frustum culling to nie warto z niego rezygnowac, bo nadaje się do każdej gry :) Occlusion culling siła rzeczy nie ma zbytnio zastosowania w grach strategicznych. Za to w RPG czy FPS to jest to konieczne jeżeli chcemy uzyskać szczegółowy obraz. Główny problem jaki rozwiązuje occlusion culling to zwykle nie liczba rysowanych na scene trójkątów, tylko liczba rysowanych obiektów. Przy dużej liczbie obiektów, wąskim gardłem zwykle staje sie procesor. Ogramna liczba zmian shaderów, tekstur, buforów itp.