Wszystkie artykuły
Tutoriale · 8 min read

Gęste listowie bez rachunku za klatki: praktyczny przewodnik

Jak wypełnić scenę roślinnością i utrzymać jej szybkość, instancing, dystanse cullingu, strategia LOD, koszty cieni, overdraw, rozmieszczenie gęstości i pętla profilowania ze stałą kamerą, która dowodzi, że każda optymalizacja naprawdę się opłaciła.

Illustration of a row of trees next to a rising frame-rate graph

W skrócie: gęstą roślinność rzadko zabija sama liczba trójkątów, umiera od tysiąca draw calli, overdraw z niedbałych kart alfa i cieni, o których nikt nie pamiętał, że są włączone. Wydawaj wysiłek w tej kolejności: instancing najpierw, dystanse cullingu drugie, cienie trzecie, LOD-y czwarte, rozmieszczenie gęstości piąte, i weryfikuj każdy krok tą samą stałą kamerą, jedną zmienną naraz, albo niczego się nie nauczysz. Ten przewodnik obejmuje każdy etap wraz z sygnaturą profilera, która mówi ci, że to twój problem.

Gęsta korona lasu odbita w spokojnym strumieniu Prawdziwy las renderuje się „za darmo", bo fizyka jest masowo równoległa. Twoje GPU może udać ten wygląd przy 60 fps, ale tylko jeśli przestaniesz sabotować machinerię, którą silniki już dostarczają dokładnie do tej roboty.

Model myślowy: pięć wąskich gardeł, jedna kolejność

Wydajność roślinności to nie jeden problem, to pięć, i dominują w przewidywalnej sekwencji. Draw calle wiążą najpierw CPU; dystans cullingu decyduje, ile w ogóle prosisz GPU narysować; cienie po cichu podwajają koszt wszystkiego, co je rzuca; LOD-y i overdraw rządzą rachunkiem na piksel; a rozmieszczenie gęstości decyduje, ile z tego wszystkiego naprawdę potrzebowałeś. Zaatakuj je w złej kolejności, a zoptymalizujesz coś, co nie było wąskim gardłem. Kolejność poniżej to ta, w której koszty faktycznie kąsają.

Instancing najpierw, cała reszta potem

Jedno drzewo narysowane 5000 razy jest radykalnie tańsze niż 5000 osobnych drzew, oba silniki batchują powtarzane siatki w draw'y instancjonowane, a twoim pierwszym zadaniem jest po prostu nie sabotować tej machinerii.

Unreal batchuje przez foliage i hierarchical instanced static meshes; Unity przez GPU instancing i szczegóły terenu. Co po cichu psuje batchowanie:

  • roślinność umieszczona jako unikalne aktory/obiekty zamiast instancji;
  • warianty materiału na instancję, używaj danych na instancję (kolor, skala) w jednym materiale zamiast tworzyć materiał na każdy wygląd;
  • rozmieszczenie rozproszone organizacyjnie, przez co silnik nie może cullować klastrów jako jednostek.

Sygnał w profilerze jest jednoznaczny: draw calle skalujące się z liczbą roślin. Jeśli widok lasu pokazuje tysiące draw calli, napraw to, zanim dotkniesz czegokolwiek innego, nic niżej na tej liście cię nie uratuje, bo jesteś CPU-bound, zanim GPU w ogóle wystartuje. Zdrowa instancjonowana roślinność trzyma draw calle w niskich setkach dla całego widoku lasu, bez względu na to, ile tysięcy roślin w nim jest.

Dystanse cullingu to darmowe pieniądze

Trawa nie musi renderować się na 800 metrów, ustaw dystanse cullingu per typ (okrywa gruntu 30–60 m, krzewy 100–200 m, tylko drzewa zasługują na długie dystanse) z zakresami fade, by ukryć popping.

To ustawienie o najwyższej wartości na minutę w całym pipeline, i rutynowo zostawiane na „nieskończoność", bo tam jest domyślnie i nikt nie zauważa. Rozumowanie jest percepcyjne: okrywa gruntu zajmuje mniej niż piksel długo przed 100 m, dosłownie nic nie wnosi do końcowego obrazu, wciąż kosztując wierzchołki, overdraw i pracę cieni każdą klatkę. Odległe pokrycie należy do tańszych systemów: koloru materiału terenu, nieprzezroczystych impostorów, albo po prostu dalekiego LOD-a warstwy terenu pomalowanej odpowiednią zielenią.

Zakresy fade (dithered lub alfa) ukrywają wyskakiwanie, by gracze nigdy nie widzieli samego dystansu cullingu. Dostrój fade akurat na tyle długi, by był niewidoczny i nie dłuższy, zbyt długi fade oznacza, że płacisz za dwie reprezentacje tej samej rośliny podczas crossfade.

Cienie: cicha połowa rachunku

Wyłącz rzucanie cieni dynamicznych dla małej okrywy gruntu, zostaw je dla drzew i ogranicz dystansowo dla krzewów, cienie trawy podwajają twój koszt przy niemal zerowym zysku wizualnym.

Każde źdźbło trawy w passie cieni jest rysowane ponownie, z punktu widzenia światła. W gęstych scenach pass cieni często kosztuje tyle co pass bazowy (co znaczy, że cienie trawy mogą być największą pojedynczą pozycją w całym budżecie roślinności, będąc wizualnie nie do odróżnienia od prostego przyciemnienia otoczenia u podstawy kępy. Naprawa jest niemal darmowa: rzucanie cieni wyłączone dla okrywy gruntu, włączone dla drzew (ich cienie robią prawdziwą pracę kompozycyjną), ograniczone dystansowo dla pośrednich. Potem sprawdź pass cieni w profilerze przed i po) zwykle jest to największa pojedyncza wygrana po instancingu, i zajmuje minuty.

LOD-y: budżetuj sylwetkę, nie poligony

Dobry łańcuch LOD roślinności zachowuje kontur i wyrzyna wnętrze, weryfikuj dystanse przejść okiem i optymalizuj najmocniej ostatni mesh LOD przed impostorem, bo to on jest na ekranie w każdym szerokim ujęciu.

Paprocie i poszycie na dnie lasu wzdłuż ścieżki Rośliny warstwy gruntowej jak te są tam, gdzie ustawienia dystansu cullingu i cienia opłacają się najbardziej, tysiące instancji, każda wnosząca niemal nic poza kilkadziesiąt metrów, każda podwajająca koszt, jeśli rzuca dynamiczny cień.

Praktyczny łańcuch dla bohaterskiego drzewa: pełna siatka → redukcja wnętrza ~50 % (ta sama sylwetka) → ~15 % ze scalonymi kartami → nieprzezroczysty impostor/billboard. Dwie uwagi oszczędzające prawdziwy ból:

  • Nawet w silnikach z geometrią zwirtualizowaną dalekie impostory nadal się opłacają, bo overdraw i cienie pozostają realnymi kosztami niezależnie od tego, jak płaci się za trójkąty. Zwirtualizowana geometria rozwiązuje liczbę trójkątów, nie koszt przezroczystości.
  • Przezroczystość to wróg na dystansie. Gęste karty alpha-tested piętrzą overdraw dokładnie tam, gdzie GPU jest najsłabsze, środkowe LOD-y. Wolej liście w siatce z bliska i nieprzezroczyste impostory z daleka; obciążony alfą środek to miejsce, gdzie chowa się czas klatki. Jeśli jeden LOD jest tajemniczo drogi, to niemal zawsze ten przezroczysty.

Overdraw: koszt, którego nie widzisz

Overdraw to GPU cieniujące ten sam piksel wielokrotnie przez spiętrzone przezroczyste powierzchnie, specyficzna klątwa roślinności, niewidoczna w końcowym obrazie i często powód, dla którego „lekka" scena jest wolna.

Większość silników ma tryb wizualizacji overdraw; włącz go i spójrz na pole trawy. Jeśli świeci na biało, cieniujesz każdy piksel pięć czy dziesięć razy, gdy nakładające się karty alfa się piętrzą. Środki zaradcze: mniej, większe źdźbła zamiast wielu cienkich; nieprzezroczysta geometria, gdzie pozwala sylwetka; i agresywne cullowanie kart wnoszących najmniej. Overdraw to klasyczny winowajca „moja scena jest wolna, ale nic nie wygląda drogo", bo trójkąty są tanie, a piksele płacone wielokrotnie.

Gęstość to decyzja projektowa, nie pozycja suwaka

Gęsto tam, gdzie gracz chodzi i patrzy, rzadko gdzie nie, pas 20 m bogatego detalu wzdłuż ścieżki czyta się jako „bujnie wszędzie" za ułamek jednolitego kosztu.

Maski nachylenia i wysokości robią część tego automatycznie (strome ściany i dalekie płaskowyże w ogóle nie potrzebują okrywy gruntu), a klasteryzacja robi resztę (kępy z lukami renderują się taniej niż jednolite wypełnienie i wyglądają naturalniej, więc wygrana wydajnościowa i estetyczna wskazują ten sam kierunek. Tu narzędzia rozmieszczania zarabiają na siebie: malowanie gęstości maskami i regułami per gatunek, a potem wypiekanie prosto do natywnych instancji silnika, to różnica między popołudniem a tygodniem. To rdzeń tego, co robi scatter Numivo) a ponieważ wypieka do zwykłego foliage i instancjonowanych siatek, każda technika w tym artykule stosuje się niezmieniona do wyniku. Nie ma runtime'u pluginu między tobą a standardowymi optymalizacjami; wypieczona scena to po prostu treść silnika.

Pętla profilowania

Ta sama kamera, ten sam widok, jedna zmienna naraz, mierz czas klatki GPU, draw calle, pass cieni i overdraw po każdej zmianie.

Wybierz stałą „kamerę budżetową" w najgęstszej panoramie i zrób zrzut statystyk przed i po każdym kroku powyżej. Dyscyplina ma znaczenie, bo optymalizacje roślinności oddziałują: zmiana dystansu cullingu zmienia, ile instancji widzi pass cieni; zmiana LOD zmienia overdraw; zmiana gęstości zmienia je wszystkie naraz. Losowe przeloty produkują losowe liczby i niefalsyfikowalne spory o to, czy zmiana pomogła. Stałe kamery produkują decyzje, których możesz bronić. Trzymaj liczby we wspólnym arkuszu, a linia trendu opowie ci historię, której pojedynczy pomiar nie potrafi.

Liczby z pola warte podkradzenia

  • Culling okrywy gruntu: 30–60 m · krzewy: 100–200 m · drzewa: linia widoku
  • Draw calle dla zdrowego instancjonowanego widoku lasu: niskie setki
  • Udział passu cieni w gęstych scenach: często ~połowa kosztu roślinności, wyłączone cienie trawy to najtańsza duża wygrana, jaka istnieje
  • Szerokość pasa dressingu wzdłuż ścieżki czytana „bujnie wszędzie": ~20 m
  • Liczba LOD dla bohaterskiego drzewa: 3 mesh LOD-y + nieprzezroczysty impostor
  • Cel overdraw dla trawy: mniej niż ~3× w widoku overdraw, nie świecące na biało 8–10× spiętrzonych kart alfa

Mini-FAQ

Czy Nanite / geometria zwirtualizowana czyni to przestarzałym? Zmienia, które pozycje dominują, nie dyscyplinę. Overdraw z kart alfa, koszt cieni i narzut na instancję pozostają, a impostory na dystansie nadal się opłacają. Mierz na docelowym sprzęcie zamiast zakładać, że nowa technologia rozwiązała twoje konkretne wąskie gardło, mogła je przesunąć, nie usunąć.

Czemu moja scena jest wolna nawet przy niskiej gęstości? Zwykli podejrzani, po kolei: trawa rzucająca dynamiczne cienie, unikalny materiał per wariant sabotujący batchowanie, dystanse cullingu na nieskończoności, albo alpha-testowy łańcuch LOD piętrzący overdraw. Każdy ma odrębną sygnaturę profilera, sprawdź przed zmianą, albo naprawisz zły.

Jak gęsto to „za gęsto" dla rozgrywki? Czytelność w walce ogranicza gęstość zanim zrobi to wydajność: jeśli sylwetki znikają w bałaganie, gracze obwiniają grę, nie dressing. Gęsto w panoramie, umiarkowanie na arenie to wzorzec, który przeżywa i profiler, i playtest.

Wypiekać czy trzymać proceduralne? Wypiekaj do wysyłki, wypieczone instancje profilują się uczciwie i wychodzą bez zależności runtime'owej. Trzymaj setup proceduralny (maski, reguły, ziarna) w kontroli wersji, byś mógł wypiec ponownie po zmianie terenu bez powtarzania pracy ręcznie.

Gęsto wyglądająca i szybka to nie sprzeczność, to głównie dyscyplina robienia pięciu rzeczy we właściwej kolejności i dowodzenia każdej tą samą kamerą.