Renderowanie w Unreal Engine
Wprowadzenie do renderowania w silnikach gier
Renderowanie odnosi się do procesu generowania ostatecznego obrazu (klatki) na ekranie ze zbioru obiektów w scenie.
Oprogramowanie używane do renderowania klatek nazywane jest render engine (silnikiem renderującym), a silniki te są zazwyczaj podzielone na kategorie:
Renderowanie offline: Zaprojektowany z myślą o wysokiej jakości renderingu, który przedkłada jakość nad czas przetwarzania. Są one zwykle używane w aplikacjach, w których czas renderowania nie jest ważny w porównaniu do jakości końcowej renderowanej klatki.
Renderowanie w czasie rzeczywistym: Zaprojektowany z myślą o wydajności i szybkim renderowaniu klatek. Typowa docelowa częstotliwość wyświetlania klatek w czasie rzeczywistym to 30 (33 ms), 60 (16 ms) i 120 (8 ms) klatek na sekundę (FPS), ale rzeczywista częstotliwość wyświetlania klatek może się zmieniać w czasie w zależności od wielu czynników. Projekty opracowane z wykorzystaniem renderowania w czasie rzeczywistym muszą znaleźć równowagę między wydajnością a jakością, aby utrzymać stałą częstotliwość wyświetlania klatek. Silniki renderujące w czasie rzeczywistym są zwykle używane w mediach interaktywnych, takich jak gry wideo, symulacje i wizualizacje architektoniczne.
Unreal Engine to potężny zestaw narzędzi zaprojektowanych do renderowania w czasie rzeczywistym, aby zaspokoić potrzeby różnych platform, od mobilnych po potężne komputery stacjonarne. Unreal Engine jest zdolny zarówno do wysokiej jakości renderowania w czasie rzeczywistym, jak i offline. Można go używać do tworzenia wszystkiego, od interaktywnych doświadczeń 2D i 3D na platformach mobilnych, konsolowych i stacjonarnych, po renderowanie końcowych klatek w produkcjach filmowych i telewizyjnych.
W przeciwieństwie do innych silników czasu rzeczywistego dostępnych na rynku, Unreal Engine oferuje wiele własnościowych funkcji zaprojektowanych specjalnie z myślą o czasie rzeczywistym i wydajności. Celem jest zmniejszenie złożoności programowania i szybsze uzyskiwanie wyników przy jednoczesnym zachowaniu wysokiej jakości i wydajności.
Funkcje takie jak system oświetlenia globalnego i odbić Lumen, wirtualizowana geometria Nanite i wirtualne mapy cieni stanowią ważny krok w kierunku osiągnięcia celu, jakim jest wyeliminowanie złożoności podczas programowania dzięki funkcjom, które „po prostu działają” w aplikacjach konsolowych i stacjonarnych. Platformy mobilne obsługują dynamiczne oświetlenie i wstępnie obliczone przepływy pracy oświetlenia, które wymagają wypalenia oświetlenia w teksturach.
Wprowadzenie do renderowania w Unreal Engine
Silniki gier wykonują serię kroków, często nazywanych potokiem renderowania, aby wyrenderować obraz (lub klatkę) na ekran. W tej sekcji opisano, w jaki sposób Unreal Engine robi to przy użyciu domyślnej ścieżki odroczonego renderowania i porównano te kroki ze ścieżką odroczonego renderowania Unity tam, gdzie to konieczne.
Silnik Unity oferuje trzy różne potoki renderowania: wbudowany, uniwersalny i wysokiej rozdzielczości. Każdy potok jest przeznaczony do określonych przypadków użycia i jest zwykle wybierany przed rozpoczęciem nowego projektu.
Unreal Engine jest wyposażony w ujednolicony potok renderowania, który skaluje poszczególne funkcje w zależności od platformy docelowej – od urządzeń podręcznych i mobilnych po konsole obecnej generacji i komputery PC. Oznacza to, że użytkownik może wybrać ścieżkę renderowania i obsługiwane funkcje, które najlepiej pasują do jego projektu, bez ograniczania się do jednej ścieżki.
Renderowanie w Unreal Engine może być używane z domyślną ścieżką odroczonego renderowania lub może być skonfigurowane tak, aby działało w ścieżce renderowania do przodu. Ponadto można włączyć mobilną ścieżkę renderowania, aby dostosować ją do urządzeń o niższej mocy, w tym do renderera mobilnego Vulkan. Więcej informacji na temat funkcji renderowania obsługiwanych dla każdej ścieżki renderowania można znaleźć w sekcji dokumentacji: Supported Features by Rendering Path (Obsługiwane funkcje według ścieżki renderowania).
Poniższy obrazek przedstawia zaawansowaną wizualizację kroków wykonywanych przez Unreal Engine w każdej klatce w celu wyrenderowania końcowego obrazu przy użyciu ścieżki odroczonego renderowania:
Proces przebiega od lewej do prawej, a kroki od 2 do 5 są wykonywane równolegle.
Poniżej użytkownik może dowiedzieć się więcej o każdym z tych kroków w potoku renderowania i o tym, co jest potrzebne do wyrenderowania każdej klatki.
Przygotowanie sceny i okluzja
Unreal Engine ma trzy podstawowe wątki – wątek gry (CPU), wątek rysowania i wątek GPU.
Przed rozpoczęciem procesu renderowania, wątek gry (lub CPU) zbiera przekształcenia wszystkich obiektów w scenie. Obejmuje to przetwarzanie wszystkich animacji, symulacji fizyki i sztucznej inteligencji (SI) przed zebraniem ostatecznego przekształcenia dla każdego obiektu.
Informacje o przekształceniu są następnie przekazywane do wątku rysowania na CPU. Wątek rysowania uruchamia proces odrzucania przed renderowaniem, który tworzy listę widocznych obiektów w bieżącym widoku kamery i usuwa wszystkie inne obiekty, które nie są widoczne dla kamery. Obiekty te nie muszą być rysowane, a brak ich renderowania poprawia wydajność.
Ten proces wykonuje następujące kroki (w kolejności):
Odrzucanie poza odległością: Usuwa wszystkie obiekty, które znajdują się dalej niż określona odległość od kamery.
Odrzucanie poza polem widzenia kamery: Usuwa obiekty, które nie są widoczne wewnątrz pola widzenia kamery.
Odrzucanie okluzji: Dokładnie sprawdza stan widoczności wszystkich pozostałych obiektów na scenie. Metoda ta jest kosztowna i dlatego jest wykonywana na końcu procesu okluzji, w którym pozostałe widoczne obiekty są dalej testowane, aby sprawdzić, czy są zasłonięte (ukryte) przez inne obiekty.
Ostateczna lista widocznych obiektów jest przekazywana do wątku GPU w celu rozpoczęcia procesu renderowania.
Odpowiednik Unity
Unity wykonuje odrzucanie poza polem widzenia i okluzji podczas swojego potoku renderowania. Ponadto może on wykonywać odrzucanie poza odległością za pomocą interfejsu API CullingGroup. Połączenie tych technik tworzy ostateczną listę widocznych obiektów w scenie.
Renderowanie geometrii
W tym kroku Unreal Engine przechodzi przez listę widocznych obiektów w scenie i przygotowuje je do następnego kroku, w którym konwertuje dane wierzchołków 3D na dane pikseli, które są wyświetlane na ekranie.
Shadery wierzchołka
Shader to fragment kodu, który działa bezpośrednio na GPU i służy do wykonywania zestawu obliczeń. Są one wydajne, a GPU może wykonywać wiele obliczeń shaderów równolegle.
Shader wierzchołków wykonuje następujące kroki:
Konwertuje lokalne pozycje wierzchołków do pozycji w świecie: Dane wierzchołków obiektów są przechowywane w przestrzeni lokalnej, ale po umieszczeniu obiektu w świecie informacje o wierzchołkach muszą zostać skonwertowane na współrzędne w przestrzeni świata.
Obsługuje cieniowanie i kolorowanie wierzchołków: Shader wierzchołków obsługuje wygładzanie wierzchołków, a także wszelkie dane kolorów wierzchołków w samym obiekcie.
Może stosować dodatkowe przesunięcia do pozycji wierzchołków: Shader wierzchołków może przesunąć pozycję dowolnego wierzchołka na ekranie w celu uzyskania określonych efektów. Odbywa się to poprzez materiał obiektu i nazywane jest przesunięciem pozycji świata.
Przejście w głąb
Przed renderowaniem poszczególnych obiektów Unreal Engine wykonuje przejście w głąb lub wczesne przejście Z, aby określić lokalizację obiektów względem siebie. Zapobiega to sytuacji, w której Unreal Engine wielokrotnie renderuje te same piksele na ekranie. Nazywa się to overdraw i może mieć znaczący wpływ na wydajność. Silnik stara się tego jak najbardziej uniknąć.
Polecenia rysowania
Po przejściu w głąb, GPU renderuje każdy obiekt poprzez rysowanie wszystkich wielokątów, które mają te same właściwości w tym samym czasie, takie jak siatki i materiały. Jest to znane jako polecenie rysowania.
Wszystkie wielokąty obiektu, którym przypisano ten sam materiał, są liczone jako to samo polecenie rysowania. Jednak każdy unikalny materiał wymaga osobnego polecenia rysowania. Na przykład, każdy obiekt na ekranie wymaga co najmniej jednego polecenia rysowania, ale może mieć ich więcej, w zależności od liczby materiałów przypisanych do obiektu.
Wirtualizowana geometria Nanite w Unreal Engine renderuje wszystkie wielokąty dla wszystkich obiektów z danym materiałem w tym samym czasie. Budżety klatek nie są już ograniczane przez liczbę wieloboków, polecenia rysowania lub wykorzystanie pamięci siatki.
Odpowiednik Unity
Potok renderowania Unity przeprowadza podobne kroki, w których wykonuje przejście w głąb i używa poleceń rysowania do rysowania obiektów na scenie.
Rasteryzacja i bufor geometrii
Rasterization process (Proces rasteryzacji) konwertuje dane wierzchołków 3D na dane pikseli 2D, które są wyświetlane na ekranie. Proces ten rozpoczyna się po zakończeniu przetwarzania wszystkich danych przez shader wierzchołków.
Geometry Buffer (GBuffer) (Bufor geometrii) Unreal Engine zawiera serię obrazów, które przechowują informacje o geometrii w scenie. Obrazy te zazwyczaj zawierają informacje o oświetleniu dla koloru bazowego, normalnej świata, metaliczności, chropowatości i odbicia światła w scenie. Te obrazy w buforze G są komponowane w celu utworzenia ostatecznego obrazu widocznego na ekranie.
Proces konwertowania tych złożonych obrazów odbywa się dla każdej renderowanej klatki i dla każdego polecenia rysowania, w którym dane wierzchołków są konwertowane na dane pikseli i rysują odpowiednie części obrazów do bufora G.
Odpowiednik Unity
Ścieżka odroczonego renderowania Unity wykorzystuje również bufor G do przechowywania krytycznych informacji o scenie. W przypadku Unity, bufor G przechowuje podobne informacje o scenie (określane różnymi nazwami): albedo, odbicie światła, normalna i emisyjna / informacje o oświetleniu dla obiektów.
Renderowanie tekstur
Unreal Engine renderuje tekstury przy użyciu streamowania tekstur, aby zoptymalizować ładowanie tekstur do sceny. System streamowania tekstur wykorzystuje mipmaps (mipmapy) tekstur. Są to wstępnie obliczone sekwencje obrazów tej samej tekstury w różnych rozdzielczościach. Można to sobie wyobrazić jako poziom szczegółów (LOD) dla tekstur zamiast siatek. Silnik automatycznie tworzy te mipmapy, w których każdy obraz ma rozdzielczość o połowę mniejszą od poprzedniego.
Unreal Engine streamuje mipmapę tekstury podczas rozgrywki w oparciu o odległość od kamery. Odbywa się to automatycznie w celu optymalizacji przesyłania danych i zużycia pamięci, a także zmniejszenia szumów w dalszej odległości od kamery.
Rozmiary tekstur muszą być potęgą liczby 2, aby można było otrzymać mipmapy. Typowe rozmiary tekstur to 3840 x 2160 pikseli (4K) i 1920 x 1080 pikseli (HD). Należy pamiętać, że tekstury nie muszą mieć określonych proporcji, tekstura 1920 x 480 pikseli również otrzyma mipmapy.
Odpowiednik Unity
System Mipmap Streaming (Streamowania mipmap) w Unity wykorzystuje mipmapy tekstur do streamowania tekstur w czasie rzeczywistym. Podobnie jak w Unreal Engine, system ten automatycznie streamuje odpowiednią mipmapę tekstury w oparciu o odległość i kąt względem kamery.
Shadery pikseli i materiały
Gdy obiekty zostaną w pełni wyrenderowane do bufora G, Unreal Engine rozpoczyna cieniowanie każdego obiektu na ekranie, wykorzystując właściwości materiału każdego obiektu za pomocą shadera pikseli.
Shader pikseli wykonuje serię obliczeń, aby zmodyfikować kolor piksela na ekranie. Shadery pikseli są uruchamianie na GPU i są niezwykle wydajne. Sterują one systemem materiałów Unreal Engine i są wykorzystywane do obliczania oświetlenia, mgły, odbić i efektów przetwarzania końcowego.
System materiałów wykorzystuje szablony shaderów High-Level Shader Language (HLSL) wraz z edytorem materiałów do tworzenia ostatecznych materiałów, które są stosowane do obiektów na ekranie. Materiały te mogą wykorzystywać parametry, takie jak tekstury, do definiowania wyglądu każdego obiektu.
Odpowiednik Unity
Unity zawiera kilka wstępnie zbudowanych shaderów (odpowiednik materiałów w Unreal Engine) wraz z Shader Graph do tworzenia shaderów dla projektu. Edytor materiałów w Unreal Engine jest odpowiednikiem grafu shaderów w Unity.
Odbicia
Po zacieniowaniu wszystkich obiektów w scenie, Unreal Engine rozpoczyna renderowanie odbić obiektów w oparciu o ich właściwości materiałów.
Unreal Engine wykorzystuje cztery systemy do renderowania odbić w scenie. Systemy te są wykonywane w następującej kolejności:
Reflection Captures (Przechwytywanie odbić): Wstępnie obliczone i przechowywane w statycznej mapie sześciennej w określonej lokalizacji.
Planar Reflections (Płaskie odbicia): Przechwytuje odbicia od płaszczyzny i na płaszczyznę.
Screen Space Reflections (SSR) (Złożone odbicia powierzchniowe (SSR)): Wykorzystuje dostępne informacje ekranu do rysowania dokładnych odbić obiektów w czasie rzeczywistym.
Lumen Reflections (Odbicia Lumen): rozwiązują odbicia dla pełnego zakresu wartości chropowatości w scenie. Odbicia te obejmują wsparcie dla światła nieba, materiałów przezroczystych, półprzezroczystości, a nawet jednowarstwowych materiałów wodnych.
Unreal Engine miesza te trzy metody, dając pierwszeństwo złożonym odbiciom powierzchniowym, następnie powracając do odbić płaskich, a na koniec do przechwytywania odbić. Ostateczny wynik odbicia jest łączony z obrazami chropowatości, odbić światła i metalicznymi w buforze G.
Jeśli używane jest oświetlenie globalne Lumen, odbicia Lumen będą używane automatycznie. Można jednak również użyć odbić Lumen bez oświetlenia globalnego Lumen, w którym to przypadku Unreal Engine użyje wypalonego oświetlenia z odbiciami Lumen.
Odpowiednik Unity
Reflection Probes Unity zapewniają podobną funkcjonalność i są używane do wstępnego obliczania danych odbicia dla sceny.
Statyczne oświetlenie i cienie
Po wyrenderowaniu odbić, Unreal Engine renderuje statyczne oświetlenie i cienie dla wszystkich obiektów w scenie.
Unreal Engine wykorzystuje system globalnego oświetlenia Lightmass do wstępnego obliczania informacji o oświetleniu sceny. Informacje o oświetleniu i cieniach są przechowywane w teksturze UV mapy oświetlenia, a tekstura ta jest mieszana z kolorem bazowym obiektu podczas renderowania obiektu w scenie.
System ten jest bardzo szybki, ale wymaga więcej pamięci i musi być wstępnie obliczany przy każdej zmianie sceny.
System globalnego oświetlenia Lightmass to dobra opcja dla projektów skierowanych na urządzenia mobilne i urządzenia o niskim poborze mocy.
Odpowiednik Unity
Progressive Lightmapper Unity i systemy Enlighten Baked Global Illumination zapewniają podobną funkcjonalność podczas wstępnego obliczania oświetlenia sceny.
Dynamiczne oświetlenie i cienie
Po wyrenderowaniu statycznego oświetlenia Unreal Engine renderuje dynamiczne (w czasie rzeczywistym) oświetlenie i cienie za pomocą Lumen, dynamicznego systemu globalnego oświetlenia.
Lumen to w pełni dynamiczny system globalnego oświetlenia i odbić, który został zaprojektowany z myślą o konsolach nowej generacji i wysokiej klasy komputerach PC. System wykorzystuje wiele metod ray tracingu, aby rozwiązywać globalne oświetlenie i odbicia na dużą skalę.
Lumen zapewnia nieskończone rozproszone odbicia i płynnie współpracuje z wirtualizowaną geometrią Nanite. Ponadto system ten działa w połączeniu z wirtualnymi mapami cieni, tworząc miękkie cienie o wysokiej rozdzielczości w czasie rzeczywistym.
Lumen zapewnia Lumen reflections (odbicia Lumen), które rozwiązują odbicia dla pełnego zakresu wartości chropowatości w scenie. Odbicia te obejmują wsparcie dla światła nieba, materiałów przezroczystych, półprzezroczystości, a nawet jednowarstwowych materiałów wodnych.
Lumen zastępuje złożone odbicia powierzchniowe, gdy jest używany w scenie.
Odpowiednik Unity
Unity wykorzystuje Enlighten Realtime Global Illumination, aby zapewnić dynamiczne oświetlenie sceny. System ten zapewnia globalne oświetlenie w czasie rzeczywistym, wykorzystując wstępnie obliczone informacje o widoczności wraz z mapami oświetlenia do obliczania pośredniego odbicia światła w czasie wykonywania.
Różni się to od Lumen, ponieważ Lumen nie wymaga żadnych wstępnie obliczonych danych, aby zapewnić pośrednie odbicia światła.
Mgła i przezroczystość
Po wyrenderowaniu dynamicznego oświetlenia i cieni, Unreal Engine renderuje mgłę i efekty przezroczystości.
Unreal Engine renderuje efekty mgły za pomocą systemu mgły zależnej wykładniczo od wysokości, który renderuje gęstość mgły na podstawie wysokości i odległości od kamery. Ponadto system może generować mgłę wolumetryczną.
Przezroczyste obiekty wykorzystują półprzezroczysty materiał i są renderowane na tym etapie procesu. Podczas korzystania z odroczonej ścieżki renderowania, Unreal Engine wykorzystuje informacje dostępne w buforze G do renderowania przezroczystości. Alternatywnie można skonfigurować materiał tak, aby korzystał ze ścieżki renderowania do przodu w celu uzyskania dokładniejszego efektu przezroczystości.
Odpowiednik Unity
Unity obsługuje Linear (liniową), Exponential (wykładniczą) i Exponential Squared (wykładniczą do kwadratu) mgłę w scenie.
Efekty przetwarzania końcowego
Po wyrenderowaniu mgły i przezroczystości, Unreal może zastosować dodatkowe efekty na obrazie. Efekty te nazywane są efektami przetwarzania końcowego, ponieważ są one stosowane po przetworzeniu końcowego obrazu. Efekty zależą od shadera pikseli i wykorzystują informacje dostępne w buforze G.
Niektóre z popularnych efektów przetwarzania końcowego obejmują poświatę, głębię ostrości, snopy świetlne, mapowanie tonów i rozmycie obrazu.
W ramach tego kroku przetwarzania końcowego Unreal Engine może zastosować superrozdzielczość czasową (TSR). TSR to niezależny od platformy czasowe zwiększenie jakości, którego Unreal Engine używa do renderowania pięknych obrazów 4K. Obrazy są dostępne za ułamek kosztów dzięki rozłożeniu niektórych kosztownych obliczeń renderowania na wiele klatek.
W łańcuchu renderowania, superrozdzielczość czasowa następuje po głębi ostrości i wszystko, co następuje po niej, ma zwiększoną jakość, jak rozmycie obrazu, poświata itd.
Po zastosowaniu tych efektów do bufora G, Unreal Engine renderuje ostateczny obraz na ekranie.
Kroki opisane powyżej generują pojedynczą klatkę na ekranie. Kroki te są często powtarzane od 30 do 60 razy na sekundę, w zależności od docelowej liczby klatek na sekundę w grze.
Odpowiednik Unity
Unity oferuje rozwiązania przetwarzania końcowego oparte na wybranym potoku renderowania. Wiele z dostępnych efektów jest podobnych do tych dostępnych w Unreal Engine.
Ponadto Unity 6 jest również wyposażony w Spatial-Temporal Post-processing (STP), natywny skaler oparty na oprogramowaniu, który wykorzystuje techniki upsamplingu przestrzennego i czasowego w celu uzyskania wysokiej jakości obrazu z antyaliasingiem.
Przegląd funkcji renderowania w Unreal Engine
Po zrozumieniu kroków podejmowanych przez Unreal Engine w celu wyrenderowania klatki na ekranie, warto dowiedzieć się więcej o konkretnych funkcjach renderowania dostępnych w silniku.
Więcej informacji na temat funkcji renderowania w Unreal Engine można znaleźć w sekcji dokumentacji: Lighting the Environment (Oświetlanie otoczenia).