Jakie są popularne techniki optymalizacji renderowania dla przejścia geometrii w odroczonym rendererze cieniowania? [Zamknięte]

16

Tworzę silnik gry przy użyciu OpenGL 3 i C ++ (i glfw do zarządzania oknami). Do tej pory posunąłem się naprzód, wykonałem większość rzeczy oprócz dźwiękowych elementów i optymalizacji. Silnik korzysta z odroczonego cieniowania, ponieważ ponieważ odroczone cieniowanie samo w sobie jest męczącym procesem dla przeciętnego procesora graficznego, chcę zoptymalizować proces renderowania w jak największym stopniu.

Obecny system składa się ze Sceny, zawierającej Renderer i obecny Świat, a Świat posiada osobne byty i byty std::vectors.

Zasadniczo za każdym razem, gdy Scena zostaje wywołana ->render()i wywołuje Renderera, przekazuje świat jako parametr i pobiera iteratory bytu ze świata, przyciąga je do FBO, a następnie przechodzi przez byty oświetlenia dla drugiego przejścia. I myślę, że to nie wystarczy.

Mój obecny algorytm iteruje wszystko, nawet jeśli bytu nie ma w obszarze ekranu. Zastanawiam się, jak zoptymalizować obecny algorytm renderowania, więc wywołuje on funkcje API tylko dla widocznych obiektów, więc jakie są typowe techniki optymalizacji takiego mechanizmu renderującego?

deniz
źródło

Odpowiedzi:

41

Odroczone cieniowanie to tylko technika „odroczenia” faktycznej operacji cieniowania na późniejszych etapach. Może to być świetne, aby zmniejszyć liczbę wymaganych przejść (na przykład), aby uzyskać 10 świateł, które wymagają 10 przejść. Chodzi mi o to, że niezależnie od używanej techniki renderowania istnieją pewne możliwe optymalizacje renderowania, które zmniejszają liczbę obiektów (wierzchołków, normalnych itp.), Które musi przetworzyć Twój potok renderowania.

Nie ma de facto standardu dla optymalizacji renderowania, a raczej szereg technik, które można stosować zamiennie lub łącznie, aby osiągnąć określone parametry wydajności. Korzystanie z każdej techniki w dużej mierze zależy od charakteru renderowanej sceny.

Odroczone renderowanie próbuje rozwiązać problem, gdy rośnie liczba świateł, co w renderowaniu do przodu może spowodować eksplozję liczby przejść.

Techniki te nie optymalizują bezpośrednio odroczonej części cieniującej, ale zgodnie z twoim opisem, odroczona część cieniująca NIE jest twoim problemem. Problem polega jednak na tym, że poddajesz całą scenę procesowi renderowania. Zatem silnik musi przetworzyć (na przykład wszystkie 100 milionów wierzchołków) w scenie, aby móc przesłać wynik do bufora g, podczas gdy większość z tych 100 milionów wierzchołków można w prosty sposób utajnić i nie przesłać do wierzchołek i fragmenty wstępnego przetwarzania przechodzą.

W przypadku mechanizmu renderującego w przód N wierzchołek będzie przetwarzany przez etap wierzchołka jako całość, vertex count*lights counta przez etap fragmentu jako całość fragments count*number Lights, odroczone cieniowanie skutecznie zmniejsza to tylko vertex countdo etapu wierzchołka i fragments countliczby fragmentów, przed rozwiązaniem rzeczywiste zacienienie. Nadal jednak N może być zbyt trudne do przetworzenia, zwłaszcza gdy większość z nich może zostać trywialnie wyrzucona.

Dzięki temu wygładzanie jest bardziej skuteczne w przypadku renderowania do przodu / wielokrotnych przejść. Należy jednak pamiętać, że większość silników korzysta z metody podwójnego renderowania, ponieważ samo odroczone cieniowanie nie jest w stanie rozwiązać przezroczystych obiektów , dlatego stosowanie tych optymalizacji jest koniecznością, nie znam żadnego komercyjnego silnika, który nie zrobiłby wszystkich z nich.

Custing Frustum

Tylko obiekty, które są całkowicie lub częściowo uwzględnione w widoku widoku, zawsze muszą być przesyłane do potoku renderowania. Jest to podstawowa koncepcja ubijania frustum, niestety sprawdzanie, czy siatka znajduje się w polu widzenia, czy frustum, może być kosztowną operacją, dlatego projektanci silników używają przybliżonej objętości granicznej, takiej jak obwiednia wyrównana do osi (AABB) lub kula ograniczająca , chociaż może to nie być tak dokładne jak użycie rzeczywistej siatki, różnica dokładności nie jest warta sprawdzenia z rzeczywistą siatką.

wprowadź opis zdjęcia tutaj

Nawet w przypadku woluminów ograniczających nie trzeba tak naprawdę sprawdzać każdego z nich, alternatywnie można zbudować hierarchię woluminów ograniczających, aby wykonać wcześniejsze ubijanie, przy czym jest to wysoce zależne od złożoności sceny.

Jest to dobra i prosta technika dla mniejszego silnika i jest prawie stosowana w każdym silniku, z którego kiedykolwiek korzystałem. Zalecam stosowanie „normalnego” sprawdzania objętości granicznej / frustracji bez hierarchii, jeśli silnik nie wymaga renderowania bardzo złożonych scen.

Hierarchia ograniczającej objętości

Odwrotna twarz

To konieczność, po co rysować twarze, które i tak nie będą widoczne? Renderowanie interfejsów API zapewnia interfejs do włączania / wyłączania wygładzania tylnej ściany. Jeśli nie masz silnego powodu, aby go nie włączyć, jak niektóre aplikacje CAD, które w pewnych okolicznościach muszą rysować backface'y, jest to konieczne.

Ubijanie okluzji

Za pomocą bufora Z można rozwiązać określenie widoczności. Problem polega jednak na tym, że bufor Z nie zawsze jest świetny pod względem wydajności, ponieważ bufor Z można rozwiązać tylko na późniejszych etapach potoku, obiekty zasłaniane powinny zostać zrasteryzowane i mogą zostać zapisane w buforze Z i Bufor kolorów przed nieudanym testem Z.

Wyrównanie okluzji rozwiązuje ten problem, wykonując kilka wczesnych testów w celu wycięcia obiektów okluzji znajdujących się w obszarze renderowania. Jedną praktyczną implementacją usuwania okluzji jest stosowanie zapytań punktowych i sprawdzanie, czy niektóre obiekty są widoczne z określonego punktu widzenia. Można to również wykorzystać do wygaszania świateł, które nie przyczyniają się do uzyskania ostatecznego obrazu, co jest szczególnie przydatne w odroczonym renderowaniu silnika.

wprowadź opis zdjęcia tutaj

Doskonałym przykładem takiej techniki jest GTA5, w której drapacze chmur są umieszczone strategicznie w centrum miasta, są nie tylko dekoracjami, ale także działają jako okludery, skutecznie zasłaniając resztę miasta i zapobiegając jego byciu zrasteryzowany.

LOD

Poziom detali

Poziom szczegółowości jest szeroko stosowaną techniką, ideą jest użycie prostszej wersji siatki, gdy siatka w mniejszym stopniu przyczynia się do sceny. istnieją dwie wspólne implementacje; jeden po prostu zamienia siatkę na prostszą, gdy nie ma już większego wpływu, siatka jest wybierana na podstawie jakiegoś czynnika, takiego jak odległość i liczba pikseli (obszar na ekranie), które zajmuje siatka. Druga wersja dynamicznie tesseluje siatkę, która jest szeroko stosowana w renderowaniu terenu.

wprowadź opis zdjęcia tutaj

Co jeśli wszystkie te nie zadziałały?

To dobre pytanie.

Pierwszą rzeczą, którą musisz zrobić, jest profilowanie aplikacji za pomocą profilera graficznego i określenie, gdzie jest wąskie gardło. Należy pamiętać, że wąskie gardło może ulec zmianie wraz ze zmianą renderowanej treści. Wąskie gardła mogą być również częścią kodu działającego na procesorze, więc również musisz to zmierzyć.

Następnie musisz dokonać optymalizacji na wąskim gardle, pamiętaj, że nie ma na to właściwej odpowiedzi i będzie się różnić od sprzętu do drugiego.

Niektóre popularne sztuczki optymalizacji GPU:

  • Unikaj rozgałęzień w shaderach.
  • Wypróbuj różne struktury wierzchołków, na przykład {VNT}przeplatane w tej samej tablicy lub {V},{N},{T}w różnych tablicach.
  • Narysuj scenę od przodu do tyłu.
  • Wyłącz bufor Z w niektórych punktach, na przykład jeśli obraz nie wymaga testowania Z.
  • Użyj skompresowanych tekstur.

Niektóre typowe triki optymalizacji procesora:

  • Użyj funkcji wbudowanych dla małych funkcji.
  • Jeśli to możliwe, użyj SIMD (wiele danych pojedynczej instrukcji).
  • Unikaj buforowania nieprzyjaznych skoków pamięci.
  • Używaj VBO z „odpowiednią” ilością danych. (w zależności od sprzętu), ale zwykle im mniej połączeń losowych, tym lepiej.

Ale co, jeśli moje wąskie gardło było w odroczonym cieniowaniu?

W tym przypadku, ponieważ odroczone cieniowanie bardziej dotyczy świateł, najbardziej oczywistą częścią jest optymalizacja faktycznych obliczeń zacienienia. niektóre z punktów, na które należy uważać:

  • Renderuj światła, które faktycznie wpływają na ostateczny obraz. Innymi słowy, wyłącz światła, które nie przyczyniają się. Można to skutecznie wdrożyć za pomocą funkcji usuwania okluzji, o której wspomniałem wcześniej.
  • Czy to światło potrzebuje odbłyśnika lub innych składników? Może nie.
  • Czy to światło rzuca cień? Niektóre światła nie muszą rzucać cieni.
  • Czy ten lekki udział można wstępnie obliczyć? Jeśli się nie porusza, prawdopodobnie pewne aspekty można wstępnie obliczyć.
concept3d
źródło
Niestety, mają one nic wspólnego z odroczonego cieniowania, one są rzeczywiście dokładne problemy z wydajnością, że łagodzi technika skutecznie i dlatego najmniej przydatne optymalizacje do wykonania, należy skupić się na przełęczy oświetlenia (ES) bo jeżeli koszt oświetlenie nie jest dominujący zabierak czasu, odroczone cieniowanie jest prawdopodobnie złym wyborem.
MickLH,
@MickLH Niestety, najwyraźniej nie przeczytałeś pytania, jego problem polegał głównie na tym, że za każdym razem iteruje całą scenę i nie wspominał o żadnym wąskim gardle dotyczącym odroczonego cieniowania. Na początku wspomniałem, że odroczone cieniowanie rozwiązuje problem wybuchu pasów przy dużej ilości światła / materiałów. Dodałem jednak, że są to optymalizacje obowiązkowe dla każdego silnika, niezależnie od techniki cieniowania do przodu lub odroczonej. Biorąc pod uwagę, że są to dokładnie te problemy, którymi migruje technika, zdecydowanie się nie zgadzam, nie mogę tutaj rozwiązać wszystkich kwestii (poniżej)
concept3d
budowanie odroczonego silnika na przykład bez wygładzania fragmentów jest naprawdę głupie, więc silnik będzie przetwarzał na przykład (100 milionów wierzchołków) tylko po to, aby móc przekazać wynik do bufora G. Zróżnicowane cieniowanie rozwiązuje inny problem, który nie był jego problemem, jego problemem było przesłanie całej geometrii do rurociągu.
concept3d
choć zgadzam się z tym, że w obliczeniach oświetlenia powinna nastąpić pewna optymalizacja, a jeśli obliczenia światła nie były dominujące, odroczenie jest niewłaściwą drogą. ale znowu to nie był jego problem.
concept3d
Wycofam moją opinię, jeśli wyjaśnisz, że te optymalizacje są w rzeczywistości najmniej skuteczne dla odroczonego renderera, ponieważ oznacza to, że nie pokazałeś mu / jej + googlerów, że problem z wydajnością nie ma nic wspólnego z odroczonym cieniowaniem.
MickLH,
6

Twój problem nie jest związany z odroczonym cieniowaniem , musisz zaimplementować podstawowe podstawowe elementy renderera, zanim spróbujesz przyspieszyć określoną część.

Kiedy skończysz z tym, co wyjaśnił concept3d, jeśli rzeczywiście okaże się, że musisz zoptymalizować sam odroczony moduł cieniujący (w przeciwieństwie do całego przejścia rasteryzacji), możesz zaimplementować odroczone cieniowanie oparte na kafelkach.

Jeśli nie jesteś ograniczony liczbą dynamicznych świateł, powinieneś rozważyć, dlaczego w ogóle używasz odroczonego cieniowania, ale jeśli tak, to spróbuj wypróbować optymalizację, która umożliwiła Battlefield 3. (Wskazują na to w slajdzie 10 swojego publicznego pliku PDF: http://dice.se/wp-content/uploads/GDC11_DX11inBF3_Public.pdf )

MickLH
źródło