Jak mogę zmniejszyć wpływ renderowania drzew na wydajność?

24

Tworzę grę w stylu low poly. Mam teren z odrobiną wody i chcę dużo drzew; W tej chwili mam 10 000 drzew. Każde drzewo składa się z nie więcej niż 200 trójkątów, więc nie są zbyt obciążające.

Głównym problemem jest to, że są jeziora, a jeziora są dość duże. Po drugiej stronie jeziora nie widać właściwie żadnych drzew, a to wygląda naprawdę źle, szczególnie gdy idziesz tam i nagle pojawiają się drzewa.

Aby to naprawić, muszę zwiększyć odległość między drzewami, abyś mógł zobaczyć przyzwoitą liczbę drzew po drugiej stronie jeziora, ale to zmniejsza wydajność do 40-50 klatek na sekundę, a w grze nie ma już nic więcej. Używam GTX 1080, jeśli to pomaga.

Co mogę zrobić, aby moja gra działała szybciej z większą liczbą drzew?

mr-matt
źródło
IIRC, Silent Hill użył mgły, aby ukryć granicę odcięcia na dalekiej płaszczyźnie odcinania, co pozwoliło im rozpocząć dynamiczne ładowanie rzeczy tuż za odcięciem mgły. Możesz skorzystać ze zmiany atmosfery gry.
Cody
Drzewa przyciągają cię do okna, obniżając w ten sposób wydajność.
mbomb007
Czy próbowałeś uruchomić profiler? Jeśli tak, to gdzie jest wąskie gardło?
Mikael Högström,
Czy robisz jakikolwiek rodzaj ubijania frustum?
Krythic
Co to jest ubijanie frustum?
mr-matt,

Odpowiedzi:

43

Istnieje kilka rzeczy, które możesz zrobić, aby zwiększyć wydajność rysowania.

  1. Powiedziałeś, że byli dość daleko. Możesz użyć LOD, aby zmniejszyć liczbę wierzchołków tych drzew, a tym samym skrócić czas potrzebny na przejście przez wszystkie narysowane wierzchołki. Chociaż najprawdopodobniej nie jest to kwestia pod ręką (GTX1080 z zaledwie 10k drzewkami po 200 tris każdy, mizerne liczby dla GPU), nadal go uwzględniam. Billboard jest skutecznym narzędziem dla najniższego poziomu LOD, ponieważ jest to zasadniczo płaska płaszczyzna zawsze zwrócona w stronę kamery z renderowanym obrazem drzewa. Traci poczucie głębi, dlatego jest dobre na najniższym poziomie, ponieważ gracz najprawdopodobniej nie zauważy różnicy.

  2. Czy włączyłeś grupowanie ? Dozowanie dynamiczne odbywa się zwykle automatycznie, jeśli liczba wierzchołków siatek jest dość niska. Partię statyczną można również wypróbować, ustawiając drzewa statycznie, zaznaczając pole wyboru w edytorze jedności na obiekcie nadrzędnym. To nie działa dobrze z animowanymi obiektami. Aby obiekty działały, potrzebujesz obiektów, które mają udostępniony materiał.

  3. Niestandardowe grupowanie pozwala kontrolować renderowanie przez samodzielne generowanie fragmentów, zamiast pozwolić jedności sobie z tym poradzić, a także umożliwia grupowanie w większe siatki. Dokonuje tego łatwo Mesh.CombineMeshes . To również nie działa dobrze z animowanymi obiektami. Aby obiekty działały, potrzebujesz obiektów, które mają udostępniony materiał. Prawdopodobnie chcesz podzielić swój świat na kilka części i tworzyć z nich partie. To, jak powinny być generowane te fragmenty, zależy od tego, jak kamera porusza się po świecie.

  4. Włącz instancję na modułach cieniujących. Instancja umożliwia silnikowi rysowanie wielu obiektów (z tą samą siatką) za pomocą tylko jednego wywołania rysowania. Aby to zadziałało, obiekty muszą mieć wspólną siatkę i udostępniony moduł cieniujący. Materiał może się różnić, ale moduł cieniujący musi obsługiwać wszystkie różne zmienne właściwości.

    Aby silnik mógł lepiej tworzyć instancyjne partie renderowania, prawdopodobnie chcesz zgrupować te same siatki w scenie. Również gra z kolejką renderowania materiału daje dobre wyniki, jeśli jedna siatka ma zawsze ten sam materiał. Podczas opracowywania gry mobilnej, nad którą obecnie pracuję, wykorzystałem ją do zmniejszenia liczby wezwań o ponad połowę w mojej scenie testowej. Również od Unity 5.6 upewnij się, że zaznaczyłeś pole Enable Instancingwyboru w materiale.

  5. Ogółem utrzymuj połączenia telefoniczne i połączenia SetPass. Są to surowe wezwania twojego GPU do rysowania rzeczy i mają one duży narzut. Zmniejszanie przeciągnięć (co to jest tworzenie partii i tworzenie instancji) zwiększy ogólną wydajność twojego procesora, ponieważ jest to wymagane o wiele mniej oczekiwania. Wywołania SetPass są zmianami w obecnych modułach cieniujących, więc jeśli masz wiele różnych materiałów, będziesz mieć wiele wywołań SetPass, które również powodują, że procesor trochę czeka.

  6. Jeśli Twoja scena jest ogromna, a Twój procesor poświęca czas na przejrzenie wszystkich obiektów na scenie, spróbuj zmniejszyć obiekty na scenie. Zgrupuj niektóre drzewa zamiast umieszczać je osobno i umieść je jako jeden obiekt. Upewnij się także, że nie przenosisz drzew ani obiektów nadrzędnych, ponieważ to powoduje, że Unity odrzuca buforowane transformacje i ponownie oblicza całe drzewo sceny.

  7. Jeśli twoja scena jest ogromna, a twój czas procesora nadal dotyczy głównie Unity przechodzącej przez drzewo scen, aby tworzyć listy do renderowania wszystkich obiektów, jedną rzeczą, którą możesz zrobić, to nie pozwolić Unity obsługiwać renderowania. Jeśli masz lepszy sposób na śledzenie obiektów rysowalnych, możesz użyć CommandBuffer.DrawMeshInstanced lub Graphics.DrawMeshInstanced, aby narysować je ręcznie. Nie będę szczegółowo omawiał tego tematu, ponieważ jest on o wiele bardziej zaawansowany i polega na wykańczaniu siebie i innych.

W przypadku, gdy grupowanie statyczne lub dynamiczne nie działa poprawnie (co widać po sprawdzeniu debuggera ramki), musisz upewnić się, że rzeczywiście korzystasz z udostępnionego materiału i nie tworzysz kopii materiału przypadkowo podczas wywoływania meshRenderer.material. Zadzwonienie .materialspowoduje wykonanie kopii twoich materiałów i przerwanie partii. Użyj .sharedMaterialzamiast tego.

Od Unity 5.6 możesz używać Debuggera Ramek, aby ustalić, dlaczego niektóre przeciągnięcia nie były wsadowe z poprzednimi przeciągnięciami. Będzie to bardzo pomocne podczas próby ograniczenia przeciągnięć w grze.

Instancje mają następujące zalety w porównaniu do grupowania statycznego / dynamicznego / niestandardowego:

  • Zużywa mniej pamięci, ponieważ siatka nie musi być duplikowana w pamięci
  • Może używać wielu materiałów, wymagany jest tylko udostępniony moduł cieniujący
  • Obiekty mogą być animowane

Wadą tego jest raczej nowa funkcja w Unity i może być nieco niestabilna. Również starsze lub GPU urządzeń mobilnych niekoniecznie obsługują instancje.

Lasse
źródło
1. Tak, próbowałem LOD i, ku mojemu zaskoczeniu, faktycznie pogorszyło się. Miałem 3 odmiany drzew, każde z nieco niższą liczbą wierzchołków, i jedną płaską płaszczyznę z renderowanym obrazem drzewa na nim.
mr-matt,
2. Wszystkie moje drzewa są oznaczone jako statyczne. O ile wiem, że umożliwia to wsadowe? Czy to jest poprawne? A kiedy mówisz o wspólnym materiale, czy masz na myśli, że drzewa mają ten sam materiał?
mr-matt,
3. Jakiego rodzaju poprawa wydajności faktycznie by to spowodowała? Czy warto próbować?
mr-matt,
1
2/3: Z mojego doświadczenia wynika, że ​​Unity nie wykonuje bardzo dobrej pracy w zakresie dynamicznego dozowania, a statyczne wiązanie wsadów zwiększa rozmiar kompilacji, więc sam wdrożyłem dozowanie i zrobiłem siatkę łączącą czas ładowania. Korzystając z tej techniki udało mi się wykonać 2500 przeciągnięć, aby skompresować je do około 300 przeciągnięć, co było kluczowe dla naszej gry mobilnej, w której ważne są przeciągnięcia. Zrobiło to trochę niepotrzebnych wierzchołków do obliczenia (poza ekranem), ale było warto.
Lasse,
2
tfw, kiedy czytasz pytanie o słabą wydajność drzew i nie tracisz ani słowa o billboardzie
Num Lock
13

Ok, więc problem polegał po prostu na tym, że nie używałem wstępnie obliczonego GI w czasie rzeczywistym. Sprawdziłem to jakiś czas temu, ale nie przyniosło to natychmiastowego efektu, więc zostawiłem to i zapomniałem o tym, a czas przetwarzania oświetlenia też był tak długi. Jednak właśnie skończył to przetwarzać i moje słowo, mój fps skoczył trzykrotnie. Więc na razie zostawię to i w przyszłości upewnij się, że zawsze używam GI w czasie rzeczywistym!

Jeśli nadal jest coś, co mógłbym zrobić, aby jeszcze bardziej poprawić wydajność, proszę dać mi znać, byłbym bardzo wdzięczny!

mr-matt
źródło
2
Użyj wygładzania okluzji, także jeśli Twoja scena jest duża - rozważ podzielenie jej na części, na przykład wiele terenów, a następnie załaduj je i rozładuj.
Candid Moon _Max_
Biorąc pod uwagę, że wydaje się, że rozwiązałeś problem, prawdopodobnie powinieneś zaakceptować tę odpowiedź.
Gnemlock