W skrócie klasyczne mapy cieni. Blog dewelopera czwarty: nowe funkcje graficzne Combat Arms

Światło ma trzy główne cechy: jasność (Mnożnik), kolor (Kolor) i cienie rzucane przez oświetlane obiekty (Cienie).

Rozmieszczając źródła światła w scenie, należy zwrócić uwagę na ich kolorystykę. Źródła światła dziennego mają niebieski odcień, ale aby stworzyć sztuczne źródło światła, należy nadać mu żółtawy kolor.

Należy również wziąć pod uwagę, że barwa źródła symulującego światło uliczne zależy od pory dnia. Dlatego też, jeśli fabuła sceny obejmuje czas wieczorny, oświetlenie może mieć czerwonawe odcienie letniego zachodu słońca.

Różne renderery oferują własne algorytmy generowania cienia. Cień rzucany przez obiekt może wiele powiedzieć – jak wysoko znajduje się nad ziemią, jaka jest struktura powierzchni, na którą pada cień, jakie źródło oświetliło obiekt itp.

Dodatkowo cień może podkreślić kontrast pomiędzy pierwszym planem a tłem, a także „oddać” obiekt, który nie znajduje się w polu widzenia obiektywu wirtualnej kamery.

W zależności od kształtu cienia rzucanego przez obiekt scena może wyglądać realistycznie (ryc. 6.6) lub nie do końca wiarygodnie (ryc. 6.7).

Jak powiedzieliśmy powyżej, rzeczywista wiązka światła ulega dużej liczbie odbić i załamań, dlatego prawdziwe cienie zawsze mają rozmyte krawędzie. W grafice 3D na określenie takich cieni stosuje się specjalny termin – cienie miękkie.

Uzyskanie miękkich cieni jest dość trudne. Wiele modułów renderujących rozwiązuje problem miękkich cieni, dodając do interfejsu 3ds max 7 niepunktowe źródło światła o kształcie prostokątnym lub innym. Takie źródło emituje światło nie z jednego punktu, ale z każdego punktu na powierzchni. Co więcej, im większy obszar źródła światła, tym delikatniejsze są cienie podczas renderowania.

Istnieją różne podejścia do renderowania cieni: użycie mapy cieni (Shadow Map), śledzenia (Raytraced) i globalnego oświetlenia (Global Illumination). Przyjrzyjmy się im w kolejności.

Ryż. 6.6. Obiekt z miękkimi cieniami

Ryż. 6.7. Obiekt z ostrymi cieniami

Ryż. 6.8. Wdrożenie ustawień parametrów mapy cieni dla źródła światła

Korzystanie z mapy cieni pozwala uzyskać rozmyte cienie

z rozmytymi krawędziami. Głównym ustawieniem Shadow Map jest rozmiar mapy cieni (parametr Size) w zestawie ustawień Shadow Map Params (ryc. 6.8). Jeśli rozmiar mapy zostanie zmniejszony, zmniejszy się również klarowność powstałych cieni.

Metoda śledzenia pozwala uzyskać idealnie ukształtowane cienie, które jednak ze względu na ostry kontur wyglądają nienaturalnie. Tracing oznacza śledzenie dróg poszczególnych promieni świetlnych od źródła światła do obiektywu aparatu, z uwzględnieniem ich odbicia od obiektów znajdujących się w scenie oraz załamania w przezroczystych ośrodkach. Metoda śledzenia jest często używana do renderowania scen zawierających odbicia lustrzane.

Począwszy od 3ds max 5, do uzyskania miękkich cieni używana jest metoda Area Shadows, która opiera się na nieco zmodyfikowanej metodzie obrysu. Cienie obszaru (Rozkład cieni) umożliwia obliczenie cieni obiektu tak, jakby w scenie nie było jednego źródła światła, ale grupa punktowych źródeł światła równomiernie rozmieszczonych na określonym obszarze.

Chociaż śledzenie promieni dokładnie odtwarza najdrobniejsze szczegóły generowanych cieni, nie jest to idealne rozwiązanie do renderowania ze względu na ostre kontury powstałych cieni.

Metoda globalnego oświetlenia (Radiosity) pozwala uzyskać miękkie cienie na ostatecznym obrazie. Metoda ta stanowi alternatywę dla śledzenia oświetlenia. Podczas gdy metoda śledzenia wizualizuje tylko te obszary sceny, które są oświetlone promieniami świetlnymi, metoda globalnego oświetlenia oblicza rozproszenie światła w nieoświetlonych lub zacienionych obszarach sceny na podstawie analizy każdego piksela obrazu. Uwzględnia to wszystkie odbicia promieni świetlnych w scenie.

Globalne oświetlenie pozwala uzyskać realistyczny obraz, jednak proces renderowania bardzo obciąża stanowisko robocze i zajmuje również dużo czasu. Dlatego w niektórych przypadkach sensowne jest zastosowanie systemu oświetleniowego symulującego efekt światła rozproszonego. W takim przypadku źródła światła należy umieścić w taki sposób, aby ich położenie pokrywało się z miejscami bezpośredniego nasłonecznienia światła. Źródła takie nie powinny dawać cieni i powinny mieć niską jasność. Ta metoda z pewnością nie daje tak realistycznego obrazu, jaki można uzyskać stosując metodę prawdziwego globalnego oświetlenia. Jednak w scenach o prostej geometrii może to być całkiem przydatne.

Istnieje kilka algorytmów obliczania oświetlenia globalnego; jedną z metod obliczania światła odbitego jest śledzenie fotonów (mapowanie fotonów). Metoda ta polega na obliczeniu oświetlenia globalnego w oparciu o utworzenie tzw. mapy fotonów. Mapa fotonów przedstawia informacje o natężeniu oświetlenia sceny zebrane podczas śledzenia.

Zaletą metody śledzenia fotonów jest to, że po zapisaniu jako mapy fotonów wyniki śledzenia fotonów można później wykorzystać do tworzenia efektów globalnego oświetlenia w scenach animacji 3D. Jakość globalnego oświetlenia obliczona za pomocą śledzenia fotonów zależy od liczby fotonów, a także głębokości śledzenia. Za pomocą śledzenia fotonów można również obliczyć efekt żrący (więcej o efekcie żrącym przeczytasz w rozdziale „Ogólne informacje o wizualizacji w grafice 3D”, rozdział 7).

Spośród standardowych źródeł światła trzy źródła (tj. Spot, Direct i Omni) pozwalają nam wybrać rodzaj cieni, które mają zostać obliczone. Jeśli skorzystamy ze standardowego domyślnego renderera Scanline (DSR), to zainteresują nas następujące elementy: Zaawansowane cienie oparte na ray tracingu, Cienie obszarowe, Cienie oparte na ray tracingu, Mapy cieni.

Kiedy wybierzesz typ cienia spośród przewijanych parametrów IS, pojawi się przewijanie parametrów cienia, którego nazwa zaczyna się od nazwy typu.

Mapa cieni

Najprostszy i najbardziej mało wymagający rodzaj cieni pod względem zasobów obliczeniowych.

  1. Rozmiar mapy, na podstawie której obliczany jest cień. Im większa mapa, tym lepsza jakość obliczonego cienia. Lepiej jest używać liczb rzędu 2 n
  2. Rozmycie krawędzi cienia. Zwiększenie parametru pozwala pozbyć się postrzępionych krawędzi, gdy rozdzielczość mapy jest niska
  3. Parametr odpowiedzialny za kontrolę wartości Bias. Domyślnie wyłączone (w większości przypadków najlepszy wynik). W przypadku animacji włączenie opcji
  4. Jeśli ta opcja jest wyłączona, światło przechodzi przez powierzchnię, jeśli uderza w wielokąty z normalnymi skierowanymi od niej. Włączenie tej opcji pozwala uzyskać prawidłowe cienie

Na ryc. 1 górny rząd obrazów wyraźnie pokazuje zmianę jakości cienia wraz ze wzrostem parametru Rozmiar. Nawet znaczne zwiększenie rozmiaru mapy nie rozwiązuje problemu postrzępionych krawędzi cienia, choć wzór cienia z pewnością staje się bardziej szczegółowy.

W drugim wierszu we wszystkich trzech przypadkach rozmiar mapy pozostaje taki sam, ale zmienia się parametr Zakres próbki. Stopniowo go zwiększając, pozbyliśmy się postrzępień, rozmywając krawędź cienia.

Ryc.1 Zmiana jakości cienia typu Shadow Map przy różnych parametrach

Cienie śledzone promieniami

Ten typ cienia jest obliczany w oparciu o algorytm śledzenia. Mają wyraźne krawędzie i praktycznie nie da się ich personalizować.

Cień wykorzystujący śledzenie promieni jest dokładniejszy w porównaniu z Mapą Cieni. Poza tym jest w stanie uwzględnić przezroczystość obiektu, ale jednocześnie jest on „suchy” i przejrzysty, co w większości przypadków nie wygląda zbyt naturalnie. Ray-Traced Shadow wymaga więcej zasobów komputera niż Shadow Map.

  1. Odległość obiektu od rzucanego cienia
  2. Głębokość śledzenia to parametr odpowiedzialny za rozwinięcie cienia. Zwiększenie tej wartości może znacznie wydłużyć czas renderowania

Renderowanie cieni wykorzystujących śledzenie promieni z układem scalonym typu Omni zajmie więcej czasu niż połączenie cieni wykorzystujących śledzenie promieni + punkt (lub tryb kierunkowy)

Rys.2 Cienie wykorzystujące śledzenie promieni z obiektów nieprzezroczystych i przezroczystych

Zaawansowane cienie oparte na ray tracingu

Cienie tego typu są bardzo podobne do cieni wykorzystujących śledzenie promieni, jednak jak sama nazwa wskazuje, posiadają bardziej zaawansowane ustawienia, które pozwalają na bardziej naturalne i poprawne obliczenia.

  1. Metoda generowania cienia
    Prosty – z układu scalonego wychodzi pojedyncza wiązka. Cień nie obsługuje żadnych ustawień wygładzania ani jakości
    1-przebiegowe antyaliasy – symulowana jest emisja wiązki promieni. Co więcej, od każdej oświetlonej powierzchni odbija się ta sama liczba promieni (liczba promieni jest dostosowywana przez jakość cienia).
    2-przebiegowe antyaliasy – Podobnie, ale emitowane są dwie wiązki promieni.
  2. Jeśli jest wyłączone, światło przechodzi przez powierzchnię, jeśli uderza w wielokąty z normalnymi skierowanymi od niej. Włączenie tej opcji pozwala uzyskać prawidłowe cienie
  3. Liczba promieni emitowanych przez oświetloną powierzchnię
  4. Liczba promieni wtórnych emitowanych przez oświetlaną powierzchnię
  5. Promień (w pikselach) rozmycia krawędzi cienia. Zwiększenie parametru poprawia jakość rozmycia. Jeśli podczas rozmycia krawędzi zostaną utracone drobne szczegóły, popraw to, zwiększając integralność cienia
  6. Odległość obiektu od rzucanego cienia
  7. Parametr kontrolujący losowość promieni. Początkowo promienie są kierowane wzdłuż ścisłej siatki, co może powodować nieprzyjemne artefakty. Wprowadzenie chaosu sprawi, że cień będzie wyglądał bardziej naturalnie
    Zalecane wartości to 0,5-1,0. Ale bardziej rozmyte cienie będą wymagały większej wartości Jitter

Cienie obszarowe

Ten rodzaj cienia pozwala uwzględnić wymiary źródła światła, dzięki czemu można uzyskać naturalne, wydłużone cienie, które „rozdzielają się” i rozmywają w miarę oddalania się od obiektu. 3dsMax tworzy te cienie poprzez zmieszanie kilku „próbek” cieni. Im więcej „próbek” i im lepsze wymieszanie, tym lepiej obliczony cień.

  1. Kształt wyimaginowanego źródła światła, który pozwala określić charakter cienia.
    Prosty – z układu scalonego wychodzi pojedyncza wiązka. Cień nie obsługuje żadnych ustawień wygładzania ani jakości.
    Światło prostokątne t – symulowana jest emisja światła z obszaru prostokątnego.
    Światło dysku – Układ scalony zachowuje się tak, jakby przyjął kształt dysku.
    Pudełko Światło – imitacja sześciennego układu scalonego.
    Światło Sfery t – imitacja sferycznego układu scalonego.
  2. Jeśli ta opcja jest wyłączona, światło przechodzi przez powierzchnię, jeśli uderza w wielokąty z normalnymi skierowanymi od niej. Włączenie tej opcji pozwala uzyskać prawidłowe cienie.
  3. Kontroluje liczbę emitowanych promieni (nieliniowa). Im wyższa liczba, tym więcej promieni, tym wyższa jakość cienia.
  4. Parametr odpowiedzialny za jakość cienia. Aby uzyskać racjonalne obliczenia, zawsze ustawiaj liczbę wyższą niż Integralność cienia.
  5. Promień (w pikselach) rozmycia krawędzi cienia. Zwiększenie parametru poprawia jakość rozmycia. Jeśli podczas rozmycia krawędzi zostaną utracone drobne szczegóły, popraw to, zwiększając integralność cienia.
  6. Odległość obiektu od rzucanego cienia.
  7. Parametr kontrolujący losowość promieni. Początkowo promienie są kierowane wzdłuż ścisłej siatki, co może powodować nieprzyjemne artefakty. Wprowadzenie chaosu sprawi, że cień będzie wyglądał bardziej naturalnie.
  8. Wymiary źródła urojonego. Długość - długość, Szerokość - szerokość, Wysokość (aktywna tylko dla światła pudełkowego i światła kulistego) - wysokość.

Przyjrzyjmy się rys.3. Na pierwszym fragmencie. Kilka „próbek” cieni nakłada się na siebie bez żadnego mieszania. W drugim fragmencie są już zmiksowane (zmiana Jitter Amount z 0.0 na 6.0). Mieszane „próbki” odbierane są jako cień bardziej naturalny, jednak ich jakość pozostawia wiele do życzenia. Trzeci fragment pokazuje cień o doskonałej jakości (Integralność cienia i Jakość cienia zmieniono z pojedynczych wartości odpowiednio na 8 i 10).

Drugi rząd na ryc. 3. ilustruje, jak zmienia się charakter cienia, jeśli zwiększamy rozmiar wyimaginowanego źródła. W tym przypadku mamy wyimaginowane źródło typu Rectangle Light (płaski prostokąt). W miarę zwiększania się obszaru źródłowego zwiększa się rozmycie cienia.

Rys.3 Zmiana jakości cienia typu Area Shadow przy różnych parametrach

Niektóre wartości parametrów mają charakter doradczy, jednak wszystko ogranicza tylko Twoja wyobraźnia. Najlepszym sposobem, aby to ustalić, jest eksperymentowanie. Nie bój się eksperymentować ze światłem. Uchwyć nastrój przyszłego obrazu i poddaj się ustawieniom.

Na ryc. 4. rycerz szachowy z materiału opartego na prostej teksturze drewna proceduralnego. Trzy źródła światła zabarwione na różne kolory. Prosta konfiguracja, ale mimo to figura wygląda dobrze.

Ryc.4 Bierka szachowa „Ryc.”. Wizualizacja tematu

Wznawiać

Oświetlenie to jeden z najważniejszych etapów pracy nad trójwymiarową sceną. Na pierwszy rzut oka może się wydawać, że suchych informacji z lekcji nie można zastosować w pracy twórczej. Jednak przy odpowiedniej pomysłowości i ciężkiej pracy można osiągnąć niesamowite rezultaty. W końcu wszystkie obrazy cyfrowe to tylko zbiory zer i jedynek, a 3dsMax to dla Ciebie po prostu kolejne narzędzie, takie jak ołówek czy pędzel.

Oryginalny algorytm mapowania cieni został wynaleziony dość dawno temu. Jego zasada działania jest następująca:
  1. Rysujemy scenę w teksturę (mapę cieni) na podstawie położenia źródła światła. Należy tutaj zauważyć, że sytuacja wygląda nieco inaczej w przypadku różnych typów źródeł światła.
    Kierunkowe źródła światła (w pewnym przybliżeniu obejmuje to również światło słoneczne) nie mają położenia w przestrzeni, ale aby utworzyć mapę cieni, należy wybrać tę pozycję. Zwykle jest ona powiązana z pozycją obserwatora, dzięki czemu mapa cieni uwzględnia obiekty znajdujące się bezpośrednio w polu widzenia obserwatora. Renderowanie wykorzystuje rzutowanie ortograficzne.
    Projekcyjne źródła światła (lampy z nieprzezroczystymi kloszami, reflektory) mają określone położenie w przestrzeni i ograniczają rozprzestrzenianie się światła w określonych kierunkach. Podczas renderowania mapy cieni w tym przypadku używana jest konwencjonalna matryca projekcji perspektywicznej.
    Dookólne źródła światła (na przykład żarówka), mimo że mają określone położenie w przestrzeni, rozprowadzają światło we wszystkich kierunkach. Aby poprawnie skonstruować cienie z takiego źródła światła, należy skorzystać z map sześciennych, co zwykle oznacza 6-krotne narysowanie sceny na mapie cieni. Nie każda gra może sobie pozwolić na dynamiczne cienie z tego rodzaju źródeł światła i nie każda gra tego potrzebuje. Jeśli interesuje Cię, jak działa to podejście, istnieje wątek na ten temat.
    Ponadto istnieje podklasa algorytmów mapowania cieni (LiSPSM, TSM, PSM itp.), które wykorzystują niestandardowe macierze projekcji widoku w celu poprawy jakości cieni i wyeliminowania niedociągnięć oryginalnego podejścia.
    Niezależnie od sposobu tworzenia mapy cieni, niezmiennie zawiera ona odległość od źródła światła do najbliższego widocznego (od położenia źródła światła) punktu lub funkcję tej odległości w bardziej skomplikowanych wersjach algorytmu.
  2. Rysujemy scenę z głównej kamery. Aby zrozumieć, czy punkt obiektu znajduje się w cieniu, wystarczy przełożyć współrzędne tego punktu na przestrzeń mapy cieni i dokonać porównania. Przestrzeń mapy cieni jest określona przez macierz rzutu widoku, która została wykorzystana do wygenerowania tej mapy. Przekładając współrzędne punktu obiektu na tę przestrzeń i przekształcając współrzędne z zakresu [-1;-1] V , otrzymujemy współrzędne tekstury. Jeśli odebrane współrzędne są poza zakresem , to punkt ten nie jest uwzględniony na mapie cieni i można go uznać za niezacieniony. Próbkując mapę cieni, korzystając z uzyskanych współrzędnych tekstury, uzyskamy odległość między źródłem światła a najbliższym mu punktem dowolnego obiektu. Jeśli porównamy tę odległość z odległością pomiędzy bieżącym punktem a źródłem światła, punkt pojawi się w cieniu, jeśli wartość na mapie cieni będzie mniejsza. Jest to dość proste z logicznego punktu widzenia, jeśli wartość z mapy cieni jest mniejsza, oznacza to, że w tym momencie jakiś obiekt jest bliżej źródła światła, a my jesteśmy w jego cieniu.
Mapowanie cieni jest obecnie prawdopodobnie najpopularniejszym algorytmem renderowania dynamicznych cieni. Implementację tej lub innej modyfikacji algorytmu można znaleźć w prawie każdym silniku graficznym. Główną zaletą tego algorytmu jest to, że zapewnia szybkie tworzenie cieni z dowolnie skomplikowanych geometrycznie obiektów. Jednocześnie istnienie szerokiej gamy odmian algorytmu wynika w dużej mierze z jego wad, które mogą prowadzić do bardzo nieprzyjemnych artefaktów graficznych. Problemy specyficzne dla PPSM i sposoby ich przezwyciężenia zostaną omówione poniżej.

Mapowanie cieni z podziałem równoległym

Rozważ następujący problem: konieczne jest rysowanie dynamicznych cieni z obiektów znajdujących się w znacznej odległości od gracza, bez pogarszania cieni z pobliskich obiektów. Ograniczmy się do skierowanego światła słonecznego.
Tego rodzaju problem może być szczególnie istotny w grach plenerowych, gdzie w niektórych sytuacjach gracz może widzieć krajobraz setki metrów przed sobą. Jednocześnie im dalej chcemy zobaczyć cień, tym więcej miejsca powinno przypadać na mapę cieni. Aby zachować odpowiednią rozdzielczość obiektów na mapie cieni, zmuszeni jesteśmy zwiększyć rozdzielczość samej mapy, co najpierw prowadzi do spadku wydajności, później natrafiamy na ograniczenie maksymalnego rozmiaru celu renderowania. W efekcie balansując pomiędzy wydajnością a jakością cieni otrzymamy cienie z wyraźnie widocznym efektem aliasingu, który jest słabo maskowany nawet przez rozmycie. Wiadomo, że takie rozwiązanie nie może nas zadowolić.
Aby rozwiązać ten problem, możemy opracować macierz projekcji, w której obiekty znajdujące się blisko gracza otrzymują na mapie cieni większy obszar niż obiekty położone daleko. Taka jest główna idea algorytmu Perspective Shadow Mapping (PSM) i szeregu innych algorytmów. Główną zaletą tego podejścia jest to, że praktycznie nie zmieniliśmy procesu renderowania sceny, zmienił się jedynie sposób obliczania macierzy widoku-rzutu. Podejście to można łatwo zintegrować z istniejącą grą lub silnikiem bez konieczności wprowadzania większych modyfikacji w tym ostatnim. Główną wadą tego rodzaju podejścia są warunki brzegowe. Wyobraźmy sobie sytuację, w której o zachodzie słońca rysujemy cienie Słońca. Gdy Słońce zbliża się do horyzontu, obiekty na mapie cieni zaczynają w dużym stopniu na siebie zachodzić. W takim przypadku nietypowa matryca projekcyjna może pogorszyć sytuację. Innymi słowy, algorytmy klasy PSM sprawdzają się dobrze w określonych sytuacjach, np. gdy gra rysuje cienie od „nieruchomego Słońca” blisko zenitu.
Zasadniczo odmienne podejście zaproponowano w algorytmie PSSM. Algorytm ten może być znany niektórym jako Cascaded Shadow Mapping (CSM). Formalnie są to różne algorytmy; powiedziałbym nawet, że PSSM jest szczególnym przypadkiem CSM. Algorytm ten proponuje podzielenie piramidy widoczności (frustum) kamery głównej na segmenty. W przypadku PSSM – z granicami równoległymi do bliższej i dalszej płaszczyzny cięcia, w przypadku CSM – rodzaj podziału nie jest ściśle regulowany. Dla każdego segmentu ( podział w terminologii algorytmu) budowana jest własna mapa cieni. Przykład podziału pokazano na poniższym rysunku.


Na rysunku widać podział piramidy widoczności na 3 segmenty. Każdy z segmentów jest zaznaczony prostokątem ograniczającym (w przestrzeni trójwymiarowej będzie równoległościan, obwiednia). Dla każdej z tych ograniczonych części przestrzeni zostanie zbudowana własna mapa cieni. Uważny czytelnik zauważy, że użyłem tutaj równoległościanów ograniczających ustawionych osiowo. Możesz także użyć niewyrównanych; zwiększy to złożoność algorytmu przycinania obiektu i nieco zmieni sposób generowania matrycy widoku na podstawie pozycji źródła światła. W miarę rozszerzania się piramidy widoczności obszar segmentów znajdujących się bliżej kamery może być znacznie mniejszy niż obszar segmentów oddalonych. Biorąc pod uwagę tę samą rozdzielczość map cieni, oznacza to wyższą rozdzielczość cieni z pobliskich obiektów. W artykule wspomnianym powyżej w GPU Gems 3 zaproponowano następujący schemat obliczania odległości podziału piramidy widoczności:



Gdzie I– indeks podziału, M– liczba przegród, N– odległość do najbliższej płaszczyzny przycinającej, F– odległość do dalszej płaszczyzny cięcia, λ – współczynnik określający interpolację pomiędzy skalą logarytmiczną i jednolitą.

Ogólne w realizacji
Algorytm PSSM zaimplementowany w Direct3D 11 i OpenGL ma wiele wspólnego. Aby zaimplementować algorytm, należy przygotować:
  1. Kilka map cieni (w zależności od liczby partycji). Na pierwszy rzut oka wydaje się, że aby uzyskać wiele map cieni, trzeba kilka razy narysować obiekty. W rzeczywistości nie jest konieczne robienie tego bezpośrednio; użyjemy mechanizmu instancji sprzętowych. Aby to zrobić, potrzebujemy tak zwanej tablicy tekstur renderujących i prostego modułu cieniującego geometrii.
  2. Mechanizm do odcinania przedmiotów. Obiekty w świecie gry mogą mieć różne kształty geometryczne i zajmować różne pozycje w przestrzeni. Rozbudowane obiekty mogą być widoczne na kilku mapach cieni, małe obiekty tylko na jednej. Obiekt może pojawić się bezpośrednio na granicy sąsiednich segmentów i musi być narysowany za pomocą co najmniej 2 map cieni. Zatem potrzebny jest mechanizm pozwalający określić, do którego podzbioru map cieni należy dany obiekt.
  3. Mechanizm ustalania optymalnej liczby przegród. Renderowanie map cieni dla każdego segmentu na klatkę może być marnowaniem zasobów obliczeniowych. W wielu sytuacjach gracz widzi przed sobą tylko niewielką część świata gry (np. patrzy na swoje stopy, albo jego wzrok spoczywa na ścianie przed nim). Oczywiste jest, że w dużej mierze zależy to od rodzaju recenzji w grze, ale miło byłoby mieć taką optymalizację.
W rezultacie otrzymujemy następujący algorytm generowania macierzy rzutowania widoku do renderowania map cieni:
  1. Obliczamy odległości, aby podzielić piramidę widoczności dla najgorszego przypadku. W najgorszym przypadku widzimy cienie aż do płaszczyzny przycinającej odległej kamery.

    Kod

    void obliczMaxSplitDistances() ( float NearPlane = m_camera.getInternalCamera().GetNearPlane(); float farPlane = m_camera.getInternalCamera().GetFarPlane(); for (int i = 1; i< m_splitCount; i++) { float f = (float)i / (float)m_splitCount; float l = nearPlane * pow(farPlane / nearPlane, f); float u = nearPlane + (farPlane - nearPlane) * f; m_maxSplitDistances = l * m_splitLambda + u * (1.0f - m_splitLambda); } m_farPlane = farPlane + m_splitShift; }

  2. Wyznaczamy odległość kamery od najdalszego widocznego punktu obiektu rzucającego cień. Należy tutaj pamiętać, że obiekty mogą rzucać cienie lub nie. Na przykład płaski, pagórkowaty krajobraz może nie rzucać cieni; w tym przypadku za cieniowanie może odpowiadać algorytm oświetlenia. Na mapę cieni zostaną wciągnięte tylko obiekty rzucające cienie.

    Kod

    float obliczFurthestPointInCamera(const matrix44& CameraView) ( bbox3 scenebox; scenebox.begin_extend(); for (size_t i = 0; i< m_entitiesData.size(); i++) { if (m_entitiesData[i].isShadowCaster) { bbox3 b = m_entitiesData[i].geometry.lock()->getBoundingBox();< 8; i++) { vector3 corner = scenebox.corner_point(i); float z = -cameraView.transform_coord(corner).z; if (z >b.transform(m_entitiesData[i].model);

  3. scenebox.extend(b);

    Kod

    ) ) scenebox.end_extend();< m_maxSplitDistances.size(); i++) { float d = m_maxSplitDistances[i] - m_splitShift; if (m_furthestPointInCamera >float maxZ = m_camera.getInternalCamera().GetNearPlane();< m_currentSplitCount; i++) { float f = (float)i / (float)m_currentSplitCount; float l = nearPlane * pow(m_furthestPointInCamera / nearPlane, f); float u = nearPlane + (m_furthestPointInCamera - nearPlane) * f; m_splitDistances[i] = l * m_splitLambda + u * (1.0f - m_splitLambda); } m_splitDistances = nearPlane; m_splitDistances = m_furthestPointInCamera; }

  4. for (int i = 0; tj

    Kod

    bbox3 obliczFrustumBox(float NearPlane, float farPlane) ( wektor3 oko = m_camera.getPosition(); wektor3 vZ = m_camera.getOrientation().z_direction(); wektor3 vX = m_camera.getOrientation().x_direction(); wektor3 vY = m_kamera. getOrientation().y_direction(); float fov = n_deg2rad(m_camera.getInternalCamera().GetAngleOfView()); float aspekt = m_camera.getInternalCamera().GetAspectRatio(); float NearPlaneHeight = n_tan(fov * 0.5f) * NearPlane; float NearPlaneHeight * aspekt; float farPlaneHeight = n_tan(fov * 0.5f); float farPlaneWidth = farPlaneHeight * aspekt; wektor3 NearPlaneCenter = oko + vZ * farPlane box; Begin_extend(); * NearPlaneHeight)); box.extend(vector3(nearPlaneCenter - vX * NearPlaneWidth + vY * NearPlaneHeight)); NearPlaneWidth + vY * NearPlaneHeight)); box.extend(vector3(nearPlaneCenter + vX * NearPlaneWidth - vY * NearPlaneHeight));

  5. box.extend(vector3(farPlaneCenter - vX * farPlaneWidth - vY * farPlaneHeight));

    Kod

    box.extend(vector3(farPlaneCenter - vX * farPlaneWidth + vY * farPlaneHeight));

Przycinanie obiektów realizujemy za pomocą prostego testu przecięcia dwóch ograniczających równoległościanów (obiektu i odcinka piramidy widoczności). Jest tu jedna cecha, którą należy wziąć pod uwagę. Być może nie widzimy obiektu, ale możemy zobaczyć jego cień. Nietrudno się domyślić, że opisanym powyżej podejściem odetniemy wszystkie obiekty, których nie widać w głównym aparacie i nie będzie z nich żadnych cieni. Aby temu zapobiec, zastosowałem dość powszechną technikę - rozszerzyłem obwiednię obiektu wzdłuż kierunku propagacji światła, co dało przybliżone przybliżenie obszaru przestrzeni, w którym widoczny jest cień obiektu. W rezultacie dla każdego obiektu została wygenerowana tablica wskaźników mapy cieni, do której należy ten obiekt wciągnąć.

Kod

void updateShadowVisibilityMask(const bbox3& frustumBox, const std::shared_ptr & Entity, EntityData& EntityData, int splitIndex) ( bbox3 b = Entity->getBoundingBox(); b.transform(entityData.model); // automatyczne obliczanie pola cienia lightSource = m_lightManager.getLightSource(0); wektor3 lightDir = lightSource.orientation .z_direction(); float ShadowBoxL = fabs(lightDir.z)< 1e-5 ? 1000.0f: (b.size().y / -lightDir.z); bbox3 shadowBox; shadowBox.begin_extend(); for (int i = 0; i < 8; i++) { shadowBox.extend(b.corner_point(i)); shadowBox.extend(b.corner_point(i) + lightDir * shadowBoxL); } shadowBox.end_extend(); if (frustumBox.clipstatus(shadowBox) != bbox3::Outside) { int i = entityData.shadowInstancesCount; entityData.shadowIndices[i] = splitIndex; entityData.shadowInstancesCount++; } }


Przyjrzyjmy się teraz procesowi renderowania i elementom specyficznym dla Direct3D 11 i OpenGL 4.3.
Implementacja na Direct3D 11
Do zaimplementowania algorytmu w Direct3D 11 będziemy potrzebować:
  1. Tablica tekstur do renderowania map cieni. Aby utworzyć tego typu obiekt, w strukturze D3D11_TEXTURE2D_DESC znajduje się pole ArraySize. Zatem w kodzie C++ nie będziemy mieli czegoś takiego jak ID3D11Texture2D* array[N] . Z punktu widzenia interfejsu API Direct3D tablica tekstur niewiele różni się od pojedynczej tekstury. Ważną cechą podczas używania takiej tablicy w shaderze jest to, że możemy określić, do której tekstury w tablicy narysujemy ten czy inny obiekt (semantyka SV_RenderTargetArrayIndex w HLSL). Na tym polega główna różnica między tym podejściem a MRT (multiple render targets), w którym jeden obiekt jest rysowany jednocześnie we wszystkich określonych teksturach. W przypadku obiektów, które trzeba wciągnąć na kilka map cieni jednocześnie, zastosujemy instancję sprzętową, która pozwala nam na klonowanie obiektów na poziomie GPU. W tym przypadku obiekt można wciągnąć do jednej tekstury w tablicy, a jego klony do innych. Wartość głębi będziemy przechowywać tylko na mapach cieni, dlatego użyjemy formatu tekstury DXGI_FORMAT_R32_FLOAT.
  2. Specjalny próbnik tekstur. W API Direct3D możesz ustawić specjalne parametry próbkowania z tekstury, co pozwoli ci porównać wartość w teksturze z podaną liczbą. Wynik w tym przypadku będzie wynosił 0 lub 1, a przejście pomiędzy tymi wartościami można wygładzić za pomocą filtra liniowego lub anizotropowego. Aby utworzyć próbnik w strukturze D3D11_SAMPLER_DESC należy ustawić następujące parametry:

    SamplerDesc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT; samplerDesc.ComparisonFunc = D3D11_COMPARISON_LESS; samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_BORDER; samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_BORDER; próbnikOpis.BorderColor = 1.0f; próbnikOpis.BorderColor = 1.0f; próbnikOpis.BorderColor = 1.0f; próbnikOpis.BorderColor = 1.0f;
    W ten sposób będziemy mieli filtrowanie dwuliniowe, porównanie z funkcją „mniej niż” i próbkowanie tekstury o współrzędnych spoza zakresu zwróci 1 (tj. brak cienia).

Rendering wykonamy według następującego schematu:

Implementacja na OpenGL 4.3
Aby zaimplementować algorytm w OpenGL 4.3, potrzebujemy wszystkiego tego samego, co w przypadku Direct3D 11, ale są subtelności. W OpenGL możemy wykonać porównywalne pobieranie tylko dla tekstur zawierających wartość głębi (na przykład w formacie GL_DEPTH_COMPONENT32F). Dlatego będziemy renderować tylko do bufora głębi i usuniemy nagrywanie do koloru (a dokładniej, do bufora ramki powiążemy tylko tablicę tekstur, aby przechowywać bufor głębi). To z jednej strony zaoszczędzi nam trochę pamięci wideo i ułatwi potok graficzny, z drugiej strony zmusi nas do pracy ze znormalizowanymi wartościami głębi.
Parametry próbkowania w OpenGL można powiązać bezpośrednio z teksturą. Będą one identyczne z tymi omówionymi wcześniej dla Direct3D 11.

Stała liczba zmiennoprzecinkowa BORDER_COLOR = ( 1.0f, 1.0f, 1.0f, 1.0f ); glBindTexture(m_shadowMap->getTargetType(), m_shadowMap->getDepthBuffer()); glTexParameteri(m_shadowMap->getTargetType(), GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(m_shadowMap->getTargetType(), GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(m_shadowMap->getTargetType(), GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); glTexParameteri(m_shadowMap->getTargetType(), GL_TEXTURE_COMPARE_FUNC, GL_LESS); glTexParameteri(m_shadowMap->getTargetType(), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(m_shadowMap->getTargetType(), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glTexParameterfv(m_shadowMap->getTargetType(), GL_TEXTURE_BORDER_COLOR, BORDER_COLOR); glBindTexture(m_shadowMap->getTargetType(), 0);
Interesujący jest proces tworzenia szeregu tekstur, który jest reprezentowany przez trójwymiarową teksturę wewnątrz OpenGL. Do jego utworzenia nie stworzono żadnej specjalnej funkcji, oba są tworzone przy użyciu glTexStorage3D . Odpowiednikiem SV_RenderTargetArrayIndex w GLSL jest wbudowana zmienna gl_Layer.
Schemat renderowania również pozostaje taki sam:

Problemy

Algorytm mapowania cieni i jego modyfikacje stwarzają wiele problemów. Często algorytm musi być starannie dostrojony do konkretnej gry lub nawet konkretnej sceny. Listę najczęstszych problemów i sposobów ich rozwiązania można znaleźć. Podczas wdrażania PSSM napotkałem następujące kwestie:

Wydajność

Pomiary wydajności przeprowadzono na komputerze o następującej konfiguracji: AMD Phenom II X4 970 3,79 GHz, 16 Gb RAM, AMD Radeon HD 7700 Series, z systemem Windows 8.1.

Średni czas trwania klatki. Direct3D 11 / 1920x1080 / MSAA 8x / pełny ekran / mała scena (~12 tys. wielokątów na klatkę, ~20 obiektów)

Średni czas trwania klatki. OpenGL 4.3 / 1920x1080 / MSAA 8x / pełny ekran / mała scena (~12 tys. wielokątów na klatkę, ~20 obiektów)

Średni czas trwania klatki. 4 podziały / 1920x1080 / MSAA 8x / pełny ekran / duża scena (~1000 tys. wielokątów na klatkę, ~1000 obiektów, ~500 instancji obiektów)

Wyniki pokazały, że implementacja OpenGL 4.3 jest ogólnie szybsza w dużych i małych scenach. W miarę wzrostu obciążenia potoku graficznego (zwiększanie liczby obiektów i ich instancji, zwiększanie rozmiaru map cieni) różnica w szybkości działania pomiędzy implementacjami maleje. Zaletę implementacji OpenGL przypisuję sposobowi generowania map cieni, który różni się od Direct3D 11 (użyliśmy jedynie bufora głębi bez zapisu do koloru). Nic nie stoi na przeszkodzie, abyśmy zrobili to samo na Direct3D 11, rezygnując jednocześnie ze stosowania znormalizowanych wartości głębi. Jednak to podejście będzie działać tylko do czasu, gdy będziemy chcieli przechowywać dodatkowe dane lub funkcję wartości głębi na mapie cieni zamiast wartości głębi. Niektóre ulepszenia algorytmu (na przykład mapowanie cieni wariancji) będą dla nas trudne do wdrożenia.

Wnioski

Algorytm PSSM jest jedną z najskuteczniejszych metod tworzenia cieni w dużych otwartych przestrzeniach. Opiera się na prostej i przejrzystej zasadzie podziału, którą można łatwo skalować, zwiększając lub zmniejszając jakość cieni. Algorytm ten można połączyć z innymi algorytmami mapowania cieni, aby uzyskać piękniejsze, miękkie cienie lub te, które są fizycznie poprawne. Jednocześnie algorytmy klasy Shadow Mapping często prowadzą do pojawienia się nieprzyjemnych artefaktów graficznych, które należy wyeliminować poprzez dostrojenie algorytmu pod konkretną grę.

Tagi:

  • Mapowanie cieni
  • PSSM
  • Direct3D 11
  • OpenGL4
Dodaj tagi

Blog deweloperów czwarty: nowe funkcje graficzne

W pierwszym dzienniku aktualizacji silnika graficznego krótko omówiliśmy niektóre nowe ulepszenia graficzne, które wkrótce zostaną dodane do gry. Dodatkowo stwierdziliśmy, że większość tych ulepszeń będzie na równi z nowoczesnymi silnikami gier, takimi jak Unity 5, Unreal 4 czy CryEngine 3. Ale co to właściwie oznacza?

Przede wszystkim chcemy, abyście zrozumieli, że proces aktualizacji będzie przebiegał stopniowo i nie wszystkie mapy, postacie, tekstury broni i obiekty zostaną zaktualizowane natychmiast. Większość z nich będzie nadal działać z obecnymi zasobami gry, ale z czasem będziemy je aktualizować, aby nadać Combat Arms naprawdę aktualny wygląd.

Warto zauważyć, że uruchomienie wielu funkcji graficznych na tak starym silniku, przy jednoczesnym zachowaniu kompatybilności wstecznej ze starym trybem graficznym i zasobami, wymagało od nas wykonania wielu interesujących, a czasem szalonych obejść, ograniczonych do możliwości DirectX 9 To była świetna zabawa!

Dynamiczne oświetlenie i cienie

Oryginalny silnik Lithitech Jupiter w ograniczonym stopniu obsługiwał dynamiczne oświetlenie i cienie, chociaż to, co oferował silnik, było dość zaawansowane jak na epokę, w której został opracowany. Zasadniczo w oryginalnym silniku graficznym Lithtech Jupiter oświetlenie i cieniowanie były całkowicie statyczne, co oznacza, że ​​zostały wstępnie obliczone i zapisane jako tekstura używana podczas renderowania geometrii mapy. Jednak nawet statyczne oświetlenie w niektórych punktach pozwoliło im stworzyć dynamicznie oświetlone sceny na określonych obiektach, takich jak modele postaci i broń. Ponieważ na obiektach zastosowano dynamiczne oświetlenie per wierzchołek, różne dodatkowe szczegóły i nierówności również musiały zostać wstępnie obliczone i wtopione bezpośrednio w rozproszone tekstury. A ponieważ są upieczone, nie mogą dynamicznie oddziaływać z różnymi źródłami światła i często nie dopasowują się do warunków oświetleniowych. To sprawia, że ​​obraz wygląda na bardzo płaski i przestarzały jak na rok 2017.

Najważniejszym usprawnieniem, jakie udało nam się wdrożyć, było połączenie zarówno statycznej geometrii mapy, jak i obiektów otrzymujących w pełni dynamiczne oświetlenie i cienie. Dynamiczne oświetlenie naprawdę umożliwia renderowanie sceny z oświetleniem piksel po pikselu, odbiciami, światłami, dynamicznymi cieniami i mapami wypukłości.

Chociaż wprowadzenie pojedynczego dynamicznego źródła światła początkowo nie było takie trudne, pojawiły się wyzwania związane z koniecznością jednoczesnej obsługi wielu dynamicznych źródeł światła w efektywny sposób. Obsługa wielu dynamicznych źródeł światła stała się podstawową cechą prawie każdego nowoczesnego silnika gier. Jedynym sposobem, w jaki silnik Lithtech wspierał renderowanie wielu dynamicznych świateł, było wielokrotne przerysowanie całej sceny, raz dla każdego światła na mapie. To trochę przesada, ponieważ Lithtech jest w stanie grupować geometrię mapy w bloki, które można wykonać za pomocą ograniczającej kuli światła, i tylko te bloki mapy będą musiały zostać przerysowane. Jednak w dalszym ciągu wymaga to dużego obciążenia procesora do wielokrotnego renderowania sceny i nakłada jeszcze większe ograniczenia na złożoność geometrii mapy i liczbę obiektów, które można wyświetlić na ekranie jednocześnie.

Zaczęliśmy od posiadania głównego kierunkowego światła słonecznego jako jedynego dynamicznego źródła światła na początku. Wszystkie pozostałe wewnętrzne źródła światła dookólnego i punktowego pozostały nieruchome. Jednak wiele lokalizacji w grze Combat Arms jest częściowo lub w całości zlokalizowanych w budynkach, więc różnica między statycznym oświetleniem wewnętrznym i dynamicznym oświetleniem zewnętrznym była zbyt zauważalna.

Zatem w przypadku dynamicznego oświetlenia wykorzystującego wiele źródeł światła konieczne było wprowadzenie dużych zmian w sposobie renderowania sceny przez silnik i obsłudze samego światła. Aby to zrobić, zastosowaliśmy technikę renderowania znaną jako Odroczone cieniowanie. Temat odroczonego oświetlenia i cieniowania może być dość szeroki i pokrótce wspomnieliśmy o nim w pierwszym poście na blogu deweloperów. Zasadniczo pozwala na przeniesienie całego dynamicznego oświetlenia do sfery renderowania postprocesowego, które jest całkowicie niezależne od złożoności sceny i może być obsługiwane prawie w całości przez procesor graficzny przy bardzo niewielkim obciążeniu procesora.

Mając na uwadze wszystkie te optymalizacje, byliśmy w stanie zaimplementować złożony moduł cieniujący oświetlenie fizyczne. Następnie dokładnie przetestowaliśmy ten model oświetlenia, porównując go z tym, jak podobne sceny byłyby renderowane w innych nowoczesnych silnikach gier, takich jak Unity 5 i Unreal 4, a także ze scenami w pełni renderowanymi promieniami utworzonymi przy użyciu profesjonalnego renderowania offline. Ograniczyliśmy się tylko do tego, co mogliśmy wdrożyć w czasie rzeczywistym przy użyciu nowoczesnego sprzętu graficznego, korzystając z nowoczesnych shaderów oświetlenia. Wyniki są porównywalne z renderowaniem promieni, a głównymi różnicami są dokładność odbicia i tłumienie oświetlenia.

Nowe dynamiczne shadery oświetlenia w Combat Arms:

Wersja sceny wykorzystująca śledzenie promieni:

Karta cienia

Wdrażając dynamiczne cienie, stanęliśmy przed szeregiem wyzwań, aby osiągnąć najnowocześniejsze, w pełni dynamiczne cieniowanie w Combat Arms. W oryginalnym silniku Lithtech większość cieni jest wkomponowana w statyczne tekstury oświetlenia używane podczas renderowania geometrii mapy. Dlatego nie wszystkie obiekty rzucają cienie, zwłaszcza obiekty dynamiczne, ponieważ cień jest stały i nie można go zmienić. Chociaż Lithtech ma funkcję, która pozwala na tworzenie dynamicznych cieni na niektórych obiektach, nie była ona zbyt często używana w Combat Arms. Ponadto ta funkcja ma zbyt ograniczony zakres, a same obiekty dynamiczne nie mogą otrzymywać cieni.

Ostatecznie zdecydowaliśmy się zastosować w pełni dynamiczną kaskadową mapę cieni (CSM) dla głównego kierunkowego źródła światła słonecznego oraz częściowo dynamiczne rozwiązanie dla świateł dookólnych i źródeł światła wykorzystujące wstępnie obliczoną dookólną mapę cieni, którą można zastosować zarówno do geometrii świata, jak i obiektów dynamicznych. Przypomina to sposób, w jaki inne nowoczesne silniki gier zapewniają dynamiczne cieniowanie.

Czym ogólnie jest Karta Cienia? Zasadniczo jest to bardzo sprytny trik, którego używają gry i programy renderujące do symulacji dynamicznego cieniowania przyspieszanego przez GPU. https://en.wikipedia.org/wiki/Shadow_mapping.

Algorytm renderowania cieni zasadniczo radzi sobie z koniecznością renderowania sceny pod względem źródła światła na teksturę, wykorzystując ją jako punkt wejścia dla modułu cieniującego oświetlenia pikseli, a następnie używając tej tekstury do obliczenia przez procesor graficzny, czy piksel znajduje się w cień, czy nie.

W grze tekstura mapy cieni wygląda następująco:

Należy pamiętać, że ta tekstura ma nie 1, ale 4 mapy cieni. Każda z tych map cieni nazywana jest kaskadą map cieni. Wraz ze wzrostem odległości do obserwowanej powierzchni stosuje się większą kaskadę, ale z mniejszą rozdzielczością. Dzięki temu cienie rozciągają się bardzo daleko, ale nadal mieszczą się w jednej teksturze o stałym rozmiarze. W takim przypadku cienie w pobliżu obserwatora będą miały wyższą rozdzielczość. Rozdzielczość mapy cieni jest bezpośrednio powiązana z tym, jak ostre i dokładne mogą być cienie.

Ponieważ mapa cieni jest po prostu kolejną kamerą w scenie, może być renderowana dynamicznie w czasie rzeczywistym. Ustawienia jakości cieni będą miały wpływ na rozdzielczość tekstur mapy cieni.

Tak wygląda rozwiązanie mapy cieni po przefiltrowaniu.

Filtrowanie mapy cieni

Użycie samej mapy cieni może spowodować powstanie bardzo ostrych cieni. I chociaż czasami mogą wyglądać dobrze, nie jest to rzeczywistością.

W prawdziwym świecie cienie nie zawsze są twarde lub miękkie, zmieniają się w zależności od wielkości źródła światła i odległości od oświetlanego obiektu. Przykłady można zobaczyć na zdjęciu:

Zwróć uwagę, jak na tych zdjęciach cienie stają się delikatniejsze w miarę oddalania się od obiektów, które je rzucały. Większość innych współczesnych gier nadal korzysta z prostej metody filtrowania cieniowania zwanej filtrowaniem procentowym bliżej lub PCF, która stosuje stałą wartość twardości lub miękkości do wszystkich cieni.

Te zrzuty ekranu z bardzo nowoczesnych gier Doom i Overwatch pokazują, jak większość gier wykonuje proste filtrowanie cieni za pomocą PCF.

Jednak w Combat Arms zdecydowaliśmy się na wdrożenie bardziej zaawansowanej technologii filtrowania cieni, która będzie bliższa temu, co widzimy w prawdziwym życiu. W grze symulujemy to przy użyciu technologii opracowanej przez firmę NVidia o nazwie Closer Soft Shadows (PCSS).

Chociaż technologię tę wprowadzono w 2005 roku, dopiero teraz sprzęt graficzny stał się wystarczająco wydajny, aby móc korzystać z tej metody, a współczesne gry dopiero w ostatnich latach zaczęły intensywnie wykorzystywać ją do filtrowania map cieni. W chwili pisania tego bloga technologia ta nadal nie jest dostępna w Unreal 4 ani Unity 5. Chociaż technicznie rzecz biorąc, Unreal 4 zapewnia alternatywne rozwiązanie zwane śledzeniem promieni odległości, ale ogranicza się ono jedynie do rozwiązywania geometrii statycznej w celu rzucania cieni.

PCSS wyłączony:

Włączono PCSS:

Dokładne filtrowanie za pomocą PCSS zostanie zastosowane, jeśli ustawienia jakości cieni są ustawione na wysokie. Ponadto PCSS jest obecnie używany tylko do podstawowego kierunkowego światła słonecznego na wszystkich poziomach jakości. Niestety PCSS nie jest kompatybilny ze sprzętowo przyspieszanym filtrowaniem cieni. Shader Model 3 DirectX 9 nie obsługuje instrukcji modułu cieniującego Gather4, które są powszechnie używane w modułach cieniujących DirectX 10+/Shader Model 4+ do filtrowania map cieni. Ze względu na obciążenie operacyjne PCSS przy użyciu modułu cieniującego Shader Model 3 pikseli, stosowane jest filtrowanie antyaliasingowe w celu zmniejszenia obciążenia procesora graficznego.

Wielokierunkowe mapowanie cieni

W przypadku dookólnych źródeł światła sprawa jest nieco bardziej skomplikowana. Ponieważ rzucają cienie we wszystkich kierunkach, tworzenie dla nich map cieni nie jest takie proste, ponieważ scena musi zostać wyrenderowana przy użyciu jakiejś kamery 360°. Zwykle wiąże się to z renderowaniem sceny w wielu kierunkach, biorąc pod uwagę położenie źródła światła. Jednak trudno jest skalować scenę, gdy jest wiele takich źródeł światła. W tym celu użyliśmy więc wstępnie obliczonej mapy cieni, która jest obliczana tylko raz, gdy mapa jest ładowana, a nie przy każdej klatce. Wstępnie obliczona mapa cieni może rzucać cienie na dynamiczne obiekty w scenie, ale dynamiczne obiekty w scenie nie będą rzucać cieni. Aby obejść to ograniczenie, używana jest natywna funkcja cienia obiektów z silnika Lithtech, która zapewnia cienie obiektów na podstawie wstępnie obliczonych dookólnych map cieni. Łączymy to również ze śledzeniem cieni w przestrzeni ekranu, aby zapewnić obiektom szczegółowe cienie natywne i cienie kontaktowe.

Ciekawy przykład wykorzystania mapy cieni do rzutowania wielokierunkowej mapy cieni na pojedynczą teksturę:

Wykorzystuje to metodę projekcji w pełnym zakresie 360°, znaną jako parametryzacja oktaedru sferycznego lub czasami nazywana „mapowaniem oktaedrycznym”, w której kula jest odwzorowywana na pojedynczą teksturę w oparciu o jej rzut na ścianę ośmiościanu.

Tradycyjne wielokierunkowe mapy cieni wykorzystują mapę sześcienną, która wymaga co najmniej 6 różnych tekstur do przedstawienia pełnej dookólnej mapy cieni 360°, ale w przypadku tej projekcji mapy używana jest tylko 1 tekstura. Ta metoda powoduje również mniejsze zniekształcenia niż większość innych metod projektowania sferycznego 2D i w przeciwieństwie do nieopakowanej mapy sześciennej idealnie wpasowuje się w pojedynczą kwadratową teksturę. Wiele istniejących map w grze wykorzystuje dużą liczbę świateł dookólnych jako głównych źródeł światła, dzięki czemu wiele z nich obsługuje również dynamiczne cieniowanie w czasie rzeczywistym.

Podsumujmy to

Wierzymy, że to połączenie technologii oświetlenia i cieniowania nada grze bardzo nowoczesny wygląd na rok 2017, a nasze rozwiązania będą dość konkurencyjne w stosunku do tego, co oferują obecnie inne silniki gier. Chociaż same te zmiany nie wystarczą, aby „zmodernizować” grę, wciąż mamy wiele pracy do wykonania, aby ulepszyć tekstury i zasoby, które w pełni wykorzystają nowe funkcje.

Oczywiście to nie wszystkie zmiany, było to jedynie dogłębne przyjrzenie się szczegółom technicznym realizacji dynamicznego oświetlenia i cieniowania w nadchodzącej aktualizacji Combat Arms. Ponadto należy zauważyć, że pokazane zrzuty ekranu zostały wykonane przy użyciu kompilacji z bieżącymi zasobami w celu zademonstrowania funkcji graficznych. Mogą one nie odzwierciedlać dokładnie ostatecznego poziomu grafiki po wydaniu aktualizacji.

Przypominam również, że zaktualizowane ustawienia graficzne są opcjonalne i po wydaniu aktualizacji będzie można przełączać się między wersjami silnika. Opracowujemy te ulepszenia graficzne w oparciu o możliwości nowoczesnych urządzeń graficznych średniej i wysokiej klasy, odpowiednich na rok 2016. Chcemy, aby silnik gry mógł w pełni wykorzystywać nowoczesne procesory graficzne, aby zapewnić najlepszą możliwą jakość obrazu. Nadal stale testujemy i optymalizujemy nowe funkcje graficzne, ale należy pamiętać, że nieco starszy lub tańszy sprzęt może obsługiwać nowe opcje graficzne tylko przy niższych ustawieniach i rozdzielczościach. Będziemy nadal wspierać starszy silnik graficzny, więc gracze ze starszym lub słabszym sprzętem lub ci, którzy po prostu wolą klasyczny styl Combat Arms, będą mogli nadal cieszyć się grą jak wcześniej.

Pozdrawiamy, zespół Combat Arms!

Mapowanie cieni jest prawdopodobnie najtrudniejszą częścią tworzenia wizualnej reprezentacji obiektu. Wykorzystujemy je do uzyskania wypalonego światła i cienia.
Muszą być indywidualnie rozpakowane, tak aby każda część modelu miała swoje własne miejsce w przestrzeni UV i zawierała prawidłowe informacje o świetle i cieniu.
Należy pamiętać, że rozdzielczość mapy cieni jest niewielka w porównaniu z rozmiarem przestrzeni UV.
Ważne jest również, aby zrozumieć, że im bardziej poziom wymaga optymalizacji, tym niżej projektant poziomów powinien używać rozdzielczości na mapach świetlnych, czasami nawet do 8 na 8 lub 16 na 16 w przypadku mniejszych obiektów.
Tendencja ta wymaga, aby pozostawić dużo dodatkowej przestrzeni wokół każdej sekcji obiektu, tak aby obszary, które są ciemne
nie wpłynęło to na rozjaśnienia i nie zniszczyło iluzji wizualnej poprawności cieni w grze.

Istnieją 3 główne sposoby utworzenia takiego przeciągnięcia:

ROZWIŃ PUDEŁKO

Jest to często najbardziej niezawodna metoda tworzenia przeciągnięcia obiektu, ponieważ większość modeli środowiskowych ma kształt zbliżony do bloków połączonych w jakąś strukturę.
Siatka ciągła (siatka, w której nie ma części oddzielonych od części głównej) jest często bardzo przydatnym rozwiązaniem przy budowie siatki,
Rozwiązanie to pozwoli na efektywniejsze rozłożenie geometrii siatki w przestrzeni UV.
Będzie to również działać dobrze nawet w przypadku mapy cieni o niskiej rozdzielczości, ponieważ utworzy ona wtedy pojedynczy gradient od ciemnego do jasnego.
Kontrastuje to z fragmentarycznym skanem, w którym wynik będzie wydawał się bardziej niejednoznaczny i może być konieczne zwiększenie rozdzielczości mapy cieni, aby przeciwdziałać efektowi ostrych przejść.
Powinniśmy starać się tego unikać, gdzie tylko się da. Niestety czasami nie ma możliwości zastosowania niższej rozdzielczości lub pojedynczego skanu geometrii.

ROZWIJANIE PLANARNE

Metoda ta jest szczególnie przydatna w przypadku konstrukcji płaskich, takich jak ściany z kilkoma fazowaniami lub wytłoczeniami. Jest również bardzo przydatny w przypadku dużych części elewacji budynków, takich jak budynki mieszkalne.
Planarny rozwinie się znacznie lepiej, jeśli zastosujesz geometrię ciągłą, ponieważ tutaj pytanie będzie dotyczyło tylko „rozluźnienia” siatki skanującej.
Czasami dobrą zasadą jest upewnienie się, że na takim skanie jest więcej przestrzeni poziomej niż pionowej, ponieważ cienie są zwykle rzucane z boku pod nieco większym kątem.
zamiast prosto w dół. Tym samym większa przestrzeń pozioma daje większe możliwości tworzenia ostrzejszych cieni, ze względu na tendencję projektantów do wybierania oświetlenia pod kątem,
aby stworzyć ciekawsze cienie niż oświetlenie od góry do dołu.

ROZWIJANIE CYLINDRYCZNE

Większość innych kształtów można uważać za odmiany kształtu cylindrycznego, chyba że oczywiście są one zbliżone do równoległościanów lub płaszczyzn.
Rozwój cylindryczny jest dobry w przypadku wielu projektów, które mają przód i boki, ale nie mają tyłu, w przeciwnym razie zastosowalibyśmy tę metodę ROZWIŃ PUDEŁKO.

Przykłady

Była to siatka ciągła, więc łatwo było ją rozszerzyć ROZWIŃ PUDEŁKO i po prostu ułóż go poziomo, aby wykorzystać jak najwięcej przestrzeni mapy cieni.
Dolne powierzchnie, które byłyby widoczne na środkowym obrazie, zostały usunięte, ponieważ prawie zawsze będą czarne.
a gdyby były połączone z resztą skanu, cienie z nich po prostu przenikałyby ciemnymi plamami na ściany tam, gdzie nie powinno ich być. To samo dotyczy górnych powierzchni.
Tyle że zawsze byłyby lekkie.


Ta metoda rozpakowywania pozwala nam uzyskać niemal idealną mapę cieni w grze w rozdzielczości 32 na 32. Geometria nie ma szwów. Tam, gdzie powinien być cień, widzimy cienkie czarne linie, a tam, gdzie nie powinno go być, nie ma go.


Tutaj widzimy, że konieczne jest wykorzystanie maksymalnej możliwej przestrzeni, ponieważ mapa cieni i tak obejmie cały skan.
Dlatego zobaczysz znaczną różnicę między proporcjami obiektu 1 do 1 i 1 do 7. Widać też, że niektóre fragmenty skanu zostały tu oddzielone i odsunięte od głównej siatki.
Dzieje się tak, ponieważ te części zawsze pozostaną w cieniu. Nie powinny mieć wpływu na resztę mapy cieni.


Nawet na dużych fasadach, takich jak ta, Planarny pokazuje dobre rezultaty. Siatka ta jest ciągła, co ułatwia nam pracę,
ale w tym przypadku wszystko działałoby tak samo, nawet gdyby skan został podzielony na kilka pionowych lub poziomych pasków, choć konieczne było wykonanie pomiędzy nimi małych wcięć.


Jak widać, ciasna geometria ułatwiła ustawienie promieni UV. Widać także, że pomiędzy fragmentami skanu znajdują się wcięcia, dzięki czemu ciemne obszary nie wpływają na jasne.
Im niższa rozdzielczość mapy, tym większe wcięcie należy wykonać.


Można zobaczyć dość agresywne zniekształcenia na przecinających się pionowych elementach spajających balustradę.
Widać, że podpora środkowa jest podzielona na dwie części, a nie na trzy, jakbyśmy przecięli ją wzdłuż krawędzi części środkowej. Odbywa się to w celu zmniejszenia liczby szwów i zapewnienia płynnego oświetlenia na większej powierzchni.


Niektóre projekty nie przestrzegają tych prostych zasad, jak na zrzucie ekranu poniżej.


Przy tak dużej liczbie pojedynczych elementów nie mamy innego wyjścia, jak tylko zwiększyć rozdzielczość tekstur, w przeciwnym razie marnowalibyśmy dużo miejsca na wypełnienie pomiędzy skanowanymi elementami, wyglądałoby to okropnie w grze.
Podniesiono więc rozdzielczość map cieni do 128 na 128, ale nadal nie wygląda to idealnie, ale wciąż nie na tyle, aby całkowicie zniszczyć wizualny obraz obiektu w grze.


Czasami łatwo jest powiększyć obiekt; wystarczy podzielić go na kilka rozsądnych części. A potem po prostu „zrelaksuj się” podczas zamiatania. Świetnym przykładem jest obiekt poniżej.


Ta konstrukcja to zasadniczo cylinder z płaską podstawą, dlatego stosuje się te dwie podstawowe metody rozpakowywania przedmiotu.
Planarny obraca części geometrii w dół osi Z, a następnie stosuje modyfikator „relaksacji” i nieco dostosowuje położenie wierzchołków, aby upewnić się, że nic nie zostanie pokryte zbyt słabo.
W środku znajduje się obudowa podobna do podstawy, tutaj część środkowa jest podzielona i wykorzystana Planarny zamiast Cylindryczny aby zapewnić większy obszar pokrycia.
Jak zawsze bardziej skupiamy się na pokryciu niż na proporcjach 1:1. Dużą zaletą jest umieszczenie szwów w ich rzeczywistych lokalizacjach, dzięki czemu cienie będą wyglądać bardziej naturalnie.
Jeśli Twój obiekt ma głębokie nacięcia, wyjątkowo ostrą geometrię połączeń, to jest to doskonałe miejsce na ułożenie w tym miejscu szwu, jeśli oczywiście jest to wymagane.

Indeks współrzędnych mapy świetlnej

Domyślnie pierwszy zestaw UV (indeks 0) siatki statycznej zostanie użyty podczas tworzenia mapy cieni dla oświetlenia statycznego.
Oznacza to, że ten sam zestaw współrzędnych, który jest używany do nakładania materiałów na siatkę, będzie również używany do oświetlenia statycznego.
Ta metoda często nie jest idealna. Jednym z powodów jest to, że promienie UV użyte do wygenerowania mapy cieni muszą być unikalne.
co oznacza, że ​​każda powierzchnia siatki nie może zachodzić na żadną inną powierzchnię w przestrzeni UV. Powód tego jest dość oczywisty: jeśli twarze nakładają się na siebie na mapie UV,
część mapy cieni odpowiadająca tej przestrzeni zostanie zastosowana do obu ścian. Doprowadzi to do nieprawidłowego oświetlenia i pojawienia się cieni tam, gdzie w zasadzie nie powinny one występować.
Siatki statyczne mają tę właściwość Indeks współrzędnych Lightmap, co pozwala na wykorzystanie danego skanu UV do mapy cieni. Ustaw tę właściwość, aby wskazywała zestaw UV, które są prawidłowo skonfigurowane do oświetlenia.

Wykresy UV i dopełnienie

Grupy izolowanych trójkątów z sąsiadującymi promieniami UV nazywane są wykresami UV.

Skan należy podzielić na wykresy i umieścić je osobno, jeśli chcemy wykluczyć wpływ cieni jednego wykresu na drugi. Również przy robieniu wcięć należy pamiętać o prostej zasadzie:
Rozmiar wcięcia musi być większy niż 4x4 tekseli, ponieważ kompresja DXT działa z blokami dokładnie tego rozmiaru.

  1. Zmarnowane wcięcie
  2. Wymagane wcięcie

Oznacza to, że dla mapy cieni o rozdzielczości 32, dopełnienie pomiędzy częściami mapy UV powinno wynosić 12,5% całkowitej przestrzeni UV.
Należy jednak pamiętać, że użycie zbyt dużego wypełnienia pomiędzy częściami UV spowoduje marnowanie pamięci mapy cieni przy wyższych rozdzielczościach.
Im bliżej wykresów UV, tym lepiej. Zmniejszy to ilość marnowanej pamięci.


Jest to dalekie od idealnego wdrożenia.

Jednym z przykładów problemów z wdrażaniem jest nadmierna fragmentacja. Widzisz, jak cienie, które powinny pozostać na wewnętrznych częściach obiektu, cieniują zewnętrzne krawędzie.
Kolejną potencjalną pułapką jest poleganie na automatycznym rozpakowywaniu, ponieważ to również może prowadzić do tych samych problemów.


Najlepszym sposobem na utworzenie mapy sieci dla mapy cienia jest modelowanie całej siatki jako jednego ciągłego elementu lub ręczne utworzenie sieci.


W ten sposób uzyskasz pojedyncze przeciągnięcie, które prawie nie będzie miało szwów i będzie znacznie bardziej wydajne.

Efektem końcowym jest siatka, która świeci prawidłowo, bez żadnych artefaktów.


Dodatkową zaletą tej metody jest to, że zwykle zmniejsza ona również liczbę wierzchołków i trójkątów potrzebnych dla danego modelu.




KATEGORIE

POPULARNE ARTYKUŁY

2024 „kingad.ru” - badanie ultrasonograficzne narządów ludzkich