Optimieren eines XNA 2D-Spiels


56

Ist es sinnvoll, die Logik zum Überspringen des Renderns von Objekten außerhalb des Ansichtsfensters zu implementieren, oder sollte es mich nicht interessieren und das Framework dies tun lassen?

Antworten:


79

Culling ist eine Leistungsoptimierung. Es macht also keinen Sinn, es nur der Sache zuliebe zu tun. Du musst einen Grund haben.


Die GPU (nicht das XNA-Framework) entfernt Dreiecke und Pixel mit erstaunlich hoher Geschwindigkeit. Jedes von Ihnen übermittelte Dreieck muss transformiert werden (über Ihren Vertex-Shader). Dann werden diejenigen ausgesondert, die außerhalb des Bildschirms landen. Dann werden die verbleibenden Dreiecke ausgefüllt und Pixel entfernt, die außerhalb des Bildschirms liegen. Die verbleibenden Pixel werden dann (über Ihren Pixel-Shader) in den Hintergrundpuffer gezogen.

(Wenn ich "dann" sage, macht es das alles in einer massiv parallelen Pipeline.)

Daher ist es sehr selten und ungewöhnlich, dass Sie einzelne Dreiecke aussortieren müssen. Um Scheitelpunktgrenzen zu erreichen, müssen Sie eine absurd große Anzahl von Dreiecken zeichnen. Um die Grenzwerte für Füllrate, Texturabruf oder Pixelschattierung zu erreichen, müssen Sie im Allgemeinen eine hohe Tiefenkomplexität aufweisen (in diesem Fall helfen Ansichtsfenster / Kegelstumpf nicht).


Geometrie außerhalb des Bildschirms ist daher in der Regel mit geringen oder keinen Kosten verbunden.

Die Kosten - insbesondere im Zusammenhang mit dem Zeichnen von "Objekten" (normalerweise 3D-Objekten) - bestehen tatsächlich darin, diese Objekte zunächst an die GPU zu senden . Reichen Sie zu viele Objekte ein und Sie erreichen Ihr Chargenlimit (Sie erhalten einige Tausend * Chargen pro Frame).

Ich empfehle, diese Antwort und dieses verknüpfte Dia-Deck zu lesen, um eine detaillierte Beschreibung der Stapel zu erhalten.

Aus diesem Grund können Sie die Anzahl der Stapel, die Sie an die GPU senden, reduzieren, wenn Sie das Kegelstumpf-Keulen implementieren. Wenn Sie eine begrenzte Stückzahl haben, können Sie diese Grenze unterschreiten.


Nun - Ihre Frage bezieht sich auf 2D-XNA - verwenden Sie vermutlich SpriteBatch. Das ist ein bisschen anders.

Es ist kein Fehler, dass es "Sprite Batch " heißt. Was es tut, ist, die Sprites zu nehmen, die Sie zeichnen, und das Beste zu tun, um diese Sprites in so wenigen Stapeln wie möglich an die GPU zu senden , indem Sie sie zusammen stapeln.

SpriteBatch muss jedoch einen neuen Stapel starten, wenn:

  • Sie zeichnen mehr Sprites, als in einen einzelnen Stapel passen (2048 Sprites in XNA 4).
  • Du änderst die Textur (aus diesem Grund gibt es eine Option zum Sortieren nach Textur)

Keulen ist also eine geeignete Optimierung, wenn Sie auf die erste stoßen. Wenn Sie eine so große Anzahl von Sprites senden, dass Sie am Ende zu viele Batches haben (wahrscheinlich verbrauchen Sie auch Bandbreite - aber ich bin mir ziemlich sicher, dass Sie zuerst das Batch-Limit erreichen). Dies ist in der Regel nur dann der Fall, wenn Sie über eine wirklich riesige Welt verfügen. In diesem Fall können Sie also in der Regel mit einem sehr simplen, schnellen, aber ungenauen Keulen davonkommen.

Jetzt - Wenn Sie mit genügend Textur-Swaps zeichnen, um das Batch-Limit zu überschreiten, und viele von ihnen tatsächlich außerhalb des Bildschirms sind und sie aussortieren, werden Sie das Batch-Limit unterschreiten. Dann ist ja - Keulen eine Optimierung, die funktionieren wird.

Eine bessere Optimierung in diesem Fall ist die Verwendung von Texturatlanten (auch Sprite-Sheets genannt). Auf diese Weise können Sie die Anzahl der Texturwechsel und damit der Stapel reduzieren - unabhängig davon, was auf dem Bildschirm angezeigt wird oder nicht. (Dies ist der Hauptgrund, warum Sie ein Quellrechteck für Ihre Sprites angeben können.)


(Wie immer: Dies ist ein Ratschlag zur Leistungsoptimierung. Daher sollten Sie die Leistung Ihres Spiels messen und verstehen sowie die Grenzen, an denen Sie stoßen, bevor Sie sich bemühen, Optimierungen hinzuzufügen.)


5
+1 Für die Erwähnung, dass das Keulen nicht nur aus Gründen der Leistung durchgeführt werden soll, sondern wenn dies aus Gründen der Leistung erforderlich ist.
Will Marcouiller

12
+1, um mir endlich zu sagen, dass Sprite-Blätter in der Tat einen Grund haben, anders als für Programmierer / Designer Bequemlichkeit zu existieren
Bill

3
+1 für eine gute Erklärung, ich habe viel aus Ihrer Antwort gelernt.
Jesse Emond

1
Die Verknüpfung zum PDF "Batch, Batch, Batch" ist unterbrochen. Hier ist eine aktualisierte: ce.u-sys.org/Veranstaltungen/…
Marton

13

Laut einem Beitrag in den Foren von MSDN führt das XNA-Framework kein Frustum-Culling durch:

Das XNA-Framework erledigt für Sie kein Kegelstumpf-Culling - es kann nicht sein, dass es keine Ahnung hat, wo tatsächlich etwas enden wird. Alle Transformationen werden auf der GPU ausgeführt und können benutzerdefinierte Shader sein.

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

In diesem Beitrag heißt es weiter, dass es sich lohnen könnte, Ihre eigenen Objekte zu rollen, wenn Sie viele Objekte in Ihrer Szene haben.


6
Insbesondere, wenn Sie eine scrollende Karte haben (Sie sagten, es handele sich um eine 2D-Karte, dies könnte also relevant sein). Es ist nur eine Verschwendung, wenn Sie große Abschnitte zeichnen, die nicht benötigt werden. Es ist nicht besonders schwierig und Sie werden vielleicht eine Verbesserung feststellen.
Michael Coleman

1

Ich entwickle seit einigen Jahren prozedurale Voxel-Terrain-Engines in XNA. In den meisten Frames verwandeln die Motoren buchstäblich Hunderttausende von Quads. In meiner Profilerstellung habe ich festgestellt, dass Kegelstumpf und Okklusions-Culling die Leistung steigern.

Das XNA HiDef-Profil (nicht Reach) verfügt über eine OcclusionQuery-Klasse, die zum Ausführen von Occlusion Culling verwendet wird. Occlusion Culling entfernt die Quads aus einem Ansichtsfenster, die von anderen Quads nicht angezeigt werden.

Etwas anderes, das Sie berücksichtigen sollten, ist, sowohl die Generation als auch die Tesselation getrennt zu betrachten.

Wenn Sie sich also einer sehr großen Anzahl von Quads in jedem Frame nähern, der transformiert wird, müssen Sie sorgfältig überlegen, wie Sie Culling- und Threading-Techniken anwenden können, um die Framerate beizubehalten, indem Sie den Datenverkehr zu den GPU-Shadern reduzieren.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.