Optymalizacja gry 2D XNA

56

Czy sensowne jest zaimplementowanie logiki, aby pomijać renderowanie obiektów poza rzutnią, czy też nie powinienem się tym przejmować i pozwolić na to Frameworkowi?

smnbss
źródło

Odpowiedzi:

79

Culling to optymalizacja wydajności. Więc nie ma sensu robić tego tylko ze względu na to. Musisz mieć powód.


GPU (nie XNA Framework) wycina trójkąty i piksele z oślepiająco dużą prędkością. Każdy przesłany trójkąt musi zostać przekształcony (za pomocą modułu cieniującego wierzchołki). Następnie eliminuje te, które wylądują poza ekranem. Następnie wypełnia pozostałe trójkąty, eliminując piksele poza ekranem. Pozostałe piksele są następnie rysowane do bufora tylnego (za pomocą modułu cieniującego piksele).

(Kiedy mówię „wtedy” - robi to wszystko w ogromnie równoległym rurociągu.)

Jest więc bardzo rzadkie i niezwykłe, że może być konieczne wybicie poszczególnych trójkątów. Aby osiągnąć granice wierzchołków, musisz narysować absurdalnie dużą liczbę trójkątów. Aby osiągnąć limity wypełnienia, pobierania tekstur lub cieniowania pikseli, zazwyczaj musisz mieć wysoką złożoność głębi (w takim przypadku wybijanie okienka / wycięcie fragmentu nie pomoże).


Tak więc zazwyczaj geometria poza ekranem jest niewielka lub żadna.

Koszt - szczególnie w kontekście rysowania „obiektów” (zwykle obiektów 3D) - w rzeczywistości polega na przesłaniu tych obiektów do GPU . Prześlij zbyt wiele obiektów, a osiągniesz limit partii (dostajesz kilka tysięcy * partii na ramkę).

Polecam przeczytanie tej odpowiedzi i połączonego pokładu slajdów, aby uzyskać dokładny opis partii.

Z tego powodu, jeśli wdrożysz custing frustum, możesz zmniejszyć liczbę partii przesyłanych do GPU. Jeśli masz ograniczoną partię - może to przekroczyć limit.


Teraz - twoje pytanie dotyczy 2D XNA - więc prawdopodobnie używasz SpriteBatch. To jest trochę inne.

Nie jest błędem, że nazywa się to „Sprite Batch ”. Zajmuje się rysowaniem duszków i robieniem wszystkiego, co w ich mocy, aby przesyłać te duszki do GPU w jak najmniejszej liczbie partii, łącząc je razem.

Ale SpriteBatch będzie zmuszony rozpocząć nową partię, jeśli:

  • Rysujesz więcej duszków, niż może zmieścić się w jednej partii (2048 duszków w XNA 4)
  • Zmieniasz teksturę (dlatego istnieje opcja sortowania według tekstury)

Więc wybijanie jest odpowiednią optymalizacją, jeśli wybierasz się do pierwszej. Jeśli wysyłasz tak dużą liczbę duszków, że kończy się to zbyt dużą ilością partii (prawdopodobnie również zużywasz przepustowość - ale jestem pewien, że najpierw przekroczysz limit partii). Zasadniczo dzieje się tak tylko wtedy, gdy masz naprawdę ogromny świat - dzięki czemu możesz na ogół uciec od bardzo uproszczonego, szybkiego, ale niedokładnego wybijania w tym przypadku.

Teraz - jeśli rysujesz z wystarczającą liczbą zamian tekstur, aby przekroczyć limit partii, a wiele z nich faktycznie znajduje się poza ekranem, a wyrzucenie ich spowoduje przekroczenie limitu partii. Zatem tak - culling to optymalizacja, która zadziała.

Jednak - w tym przypadku lepszą optymalizacją jest zastosowanie atlasów tekstur (aka: arkuszy sprite). Pozwala to zmniejszyć liczbę zamian tekstur, a tym samym partii - niezależnie od tego, co jest wyświetlane na ekranie lub wyłączone. (To jest główny powód, dla którego możesz określić źródłowy prostokąt dla swoich duszków).


(Jak zawsze: jest to wskazówka na temat optymalizacji wydajności. Dlatego powinieneś zmierzyć i zrozumieć własną wydajność gry oraz jakie ograniczenia przekraczasz, zanim wydasz wysiłek na dodanie optymalizacji).

Andrew Russell
źródło
5
+1 Za wzmiankę o tym, aby nie robić cullingu tylko ze względu na niego, ale gdy jest to wymagane ze względu na wydajność.
Czy Marcouiller
12
+1 za to, że w końcu powiedziałem mi, że arkusze duszków rzeczywiście mają powód, by istnieć inaczej niż dla wygody programisty / projektanta
Bill
3
+1 za świetne wyjaśnienie, wiele się nauczyłem z twojej odpowiedzi.
Jesse Emond
1
Link do pliku „Batch, Batch, Batch” jest uszkodzony. Oto zaktualizowany: ce.u-sys.org/Veranstaltungen/…
Marton
13

Zgodnie z postem na forach MSDN, środowisko XNA nie wykonuje usuwania frustum:

Środowisko XNA nie będzie dla ciebie eliminowało frustum - nie mogło, ponieważ nie ma pojęcia, gdzie właściwie wszystko się skończy. Wszystkie transformacje są wykonywane na GPU i mogą być niestandardowym modułem cieniującym.

http://xboxforums.create.msdn.com/forums/p/22763/121897.aspx

Ten post mówi dalej, że jeśli masz wiele obiektów na scenie, warto je rozwinąć.

Nate
źródło
6
Zwłaszcza jeśli masz przewijaną mapę (powiedziałeś, że to 2D, więc może to być istotne). To tylko marnotrawstwo, jeśli narysujesz duże odcinki, które nie są potrzebne. To nie jest strasznie trudne i możesz zobaczyć jakąś poprawę.
Michael Coleman,
1

Od kilku lat pracuję nad silnikami wokselowymi proceduralnymi w XNA. W większości ramek silniki przekształcają dosłownie setki tysięcy quadów. W moim profilowaniu zauważyłem, że wygładzanie frustum i okluzji powoduje wzrost wydajności.

Profil XNA HiDef (nie Reach) ma klasę OcclusionQuery, która służy do wykonywania Culling okluzji. Culling okluzji usuwa te kwadraty z okienka ekranu, które są ukryte przed innymi quadami.

Inną rzeczą, którą powinieneś wziąć pod uwagę, jest osobne wprowadzanie generacji i mozaiki.

Tak więc, gdy zbliżasz się do bardzo dużej liczby quadów w każdej transformowanej ramce, musisz dokładnie przemyśleć, w jaki sposób możesz zastosować techniki wycinania i wątkowania w celu utrzymania częstotliwości klatek, zmniejszając ruch do shaderów GPU.

Jason Coombes
źródło