Wydajne renderowanie z wieloma źródłami światła

10

Aby wyrenderować scenę z pojedynczym źródłem światła za pomocą cieniowania phong, można obliczyć ostateczny kolor każdego fragmentu przekazanego do modułu cieniującego fragmenty na podstawie elementów otoczenia / rozproszonego / zwierciadlanego zarówno materiału, jak i źródła światła.

Można to łatwo rozszerzyć, aby uwzględnić wiele źródeł światła, sumując wyniki zastosowania poszczególnych źródeł światła na fragmencie jako takim:

final_color = (0, 0, 0, 1)
for each light:
    final_color += apply_light(material, light)
final_color = clamp(final_color, (0,0,0,1), (1,1,1,1))

Jednak przy bardzo dużej liczbie źródeł światła proces ten przebiega dość wolno; w przypadku Nświateł to podejście wymaga obliczenia cieniowania phong, które należy wykonać Nrazy na fragment.

Czy istnieje lepsze podejście do renderowania scen z bardzo dużą liczbą źródeł światła (setki, tysiące itp.)?

es1024
źródło

Odpowiedzi:

15

Tak, ale potrzebujesz zmiany paradygmatu.

To, co jesteś przyzwyczajony, nazywa się renderingiem do przodu. Podajesz swoją geometrię, a następnie natychmiast przystępujesz do przejścia cieniowania. W podstawowym renderowaniu do przodu możesz albo zapętlić wnętrze modułu cieniującego dla każdego światła lub wykonać jedno przejście na światło i połączyć wynik razem (z mieszaniem dodatkowym).

Ale wiele się zmieniło. Wchodzi: odroczone renderowanie

Teraz, gdy jest tak wiele wariantów, które opisują je wszystkie w szczegółach, odpowiedź będzie znacznie bardziej niż możliwa do zaakceptowania. Więc tutaj opiszę sedno odroczonego cieniowania, istnieje wiele innych zasobów, które można łatwo znaleźć za pomocą Google, mam nadzieję, że po przeczytaniu tego będziesz mieć odpowiednie słowa kluczowe, aby znaleźć to, czego potrzebujesz.

Podstawową ideą jest odłożenie cieniowania na później. Masz dwa główne kroki:

  1. Renderuj swoją geometrię i wszystkie informacje potrzebne do cieniowania do wielu celów renderowania. Oznacza to, że zazwyczaj w podstawowej implementacji miałbyś bufor głębokości, bufor zawierający wartości normalne twojej geometrii i kolor albedo. Wkrótce przekonasz się, że potrzebujesz innych informacji o materiałach (np. Szorstkość, współczynnik „metaliczny” itp.).

Ten obraz z wikipedii pokazuje trzy bufory (kolor, głębokość i normalne)

wprowadź opis zdjęcia tutaj

Ponownie ilość, rodzaj i zawartość używanych buforów różni się bardzo w różnych projektach. Znajdziesz zestaw buforów o nazwie GBuffers.

  1. Następnie nadszedł czas na zastosowanie rzeczywistego oświetlenia. Podczas przejścia światła dla każdego światła chcesz narysować objętość światła, która zależy od rodzaju światła:
    • Aby uzyskać światło kierunkowe, renderujesz czteroekranowy ekran.
    • Dla światła punktowego renderujesz kulę, której promień jest oparty na tłumieniu światła punktowego.
    • Dla światła punktowego renderujesz stożek, którego wymiary ponownie zależą od właściwości twojego światła.

W cieniowaniu pikseli tego przejścia przekazujesz swoje GBuffery i wykonujesz oświetlenie i cieniowanie z wykorzystaniem zawartych w nich informacji. W ten sposób przetwarzane są tylko piksele, na które wpływa każde ze świateł, z wyraźnym przyspieszeniem w porównaniu z klasycznym renderowaniem do przodu.

Ma także różne wady, w szczególności obsługę przezroczystych obiektów oraz większe zużycie przepustowości i pamięci wideo. Ale trudniej jest też obsługiwać różne modele materiałów.

Masz inne zalety dodatkowe (ponieważ masz dużo informacji gotowych do przetwarzania końcowego), a także jest dość łatwy do wdrożenia. Ale nie jest to już najfajniejsza rzecz dla wielu świateł.

Nowsze techniki to na przykład renderowanie sąsiadująco. Ich główną ideą jest podzielenie sceny w „kafelkach” przestrzeni ekranu i przypisanie do każdej płytki wpływających na nią świateł. Istnieje to zarówno w sposób odroczony, jak i terminowy. Techniki te prowadzą do pewnych problemów, gdy występują różne nieciągłości głębokości w kafelku, ale na ogół są szybsze niż klasyczne odroczone i rozwiązują różne problemy z tym związane. Na przykład, między zaletami, z odłożonym kafelkami odczytujesz GBuffers raz na oświetlony fragment i piksele na tym samym kafelku spójnie przetwarzają te same światła.

Dalszą ewolucją po tej stronie jest cieniowanie klastrowe, które jest koncepcyjnie podobne do podejścia opartego na kafelkach, mając zamiast kafelków przestrzeni ekranu klastry w zakresie 3D. Ta metoda lepiej radzi sobie z problemem nieciągłości głębokości i generalnie działa lepiej niż metody sąsiadująco.

WAŻNA UWAGA: Opisałem podstawy odroczonego cieniowania. Istnieje wiele odmian, optymalizacji i ulepszeń, więc zachęcam do eksperymentowania z prostą wersją, a następnie do zbadania innych technik, takich jak wspomniana powyżej.

CIFZ
źródło
1
Oto dwa zasoby kodu źródłowego dla Tiled i Clustered
RichieSams,