Ich entwickle ein 2D-Spiel und habe viele Sprites. Ich habe 3D-Animationen und -Modelle verwendet, um sie in 2D zu rendern und ihnen das Aussehen von "Fallout" oder "Diablo" zu verleihen. Es ist auch einfacher als von Hand zu zeichnen, lol.
Ich musste die Framerate bereits auf 15 fps reduzieren, was der niedrigste Wert war, den ich erreichen konnte, ohne sie abgehackt wirken zu lassen. Es war jedoch traurig, wie unglaublich glatt 24 Frames aussahen.
Es gibt zwei Gründe, warum ich das getan habe:
1) Reduzieren Sie den Festplattenspeicher. Je weniger Bilder, desto kleiner wird mein Gesamtspiel.
2) Reduzieren Sie den RAM-Verbrauch. Je weniger Bilder geladen werden müssen, desto wahrscheinlicher vermeide ich Probleme mit der RAM-Beschränkung.
Wenn es jedoch eine Möglichkeit gäbe, die Bilder sowohl im Festplattenspeicher als auch im RAM zu komprimieren, würde ich dies tun. Ich habe es schon einmal getestet und die meisten erhalten keine Qualitätsänderung, wenn sie von RGBA8888 auf RGBA5555 umsteigen, und nur einen kleinen Treffer, wenn ich in meinem TexturePacker-Programm auf RGBA4444 umsteige. Ich mache dies derzeit nicht, da SFML anscheinend dieselbe Speichermenge verwendet, unabhängig davon, um welche Art von PNG-Bild es sich handelt. Ich habe nachgeforscht, wie man es anders lädt, aber nichts zu diesem Thema gefunden.
Ich habe viel darüber gelesen, wie man mit 2D-Videospielen umgeht. Der Konsens ist überwältigend: Packe deine Sprites in eine größere Textur, um eine großartige Leistung zu erzielen! Also packe ich meine winzigen Sprites mit TexturePacker in ein viel größeres Spritesheet.
Ich plane jedoch 10-15 Animationen pro Charakter, 5 Bewegungsrichtungen und 15-40 Bilder pro Animation (wahrscheinlich durchschnittlich 24). Mit 15 Animationen, 5 Richtungen und durchschnittlich 24 Bildern pro Animation; Das sind 1800 Einzelbilder pro Zeichen. Wenn in einem Sprite-Blatt gepackt, sind das stattdessen nur 75 Bilder. (Ein Sprite-Blatt pro Animation, pro Richtung. 15 * 5)
Für den einen großen Boss im Spiel kann ich kein Spritesheet verwenden und muss eine Methode programmieren, um einfach jeweils ein Bild zu laden. Ich weiß noch nicht, ob ich das für die Aufführung tun kann.
Für die Charaktere packe ich sie bereits in ein Spritesheet. Für einen einzelnen Charakter, der herumläuft, scheint dies die meiste Zeit zu funktionieren, obwohl es manchmal zum Stillstand kommt. Ich schreibe das jedoch meinem schlecht konzipierten Code zu, der Texturen austauscht, anstatt alle Texturen für dieses Zeichen vorzuladen.
Wenn ich die Texturen vorlade, ist das für Sprite-Sheets sinnvoll. Ich würde mir nur vorstellen, dass es eine schlechte Idee ist, 1800 winzige Bilder für jeden Charakter vorzuladen.
Ich stelle mir jedoch vor, dass es extrem schnell ist, sie nacheinander in den Speicher zu streamen und wieder aus dem Speicher zu entfernen, sodass ich immer nur ein einziges Bild im Speicher haben muss. Würde das nicht bedeuten, dass ich zu jedem Zeitpunkt nur ein paar KB anstelle von 45 + MB pro Zeichen verbrauchen würde?
Ich stelle mir vor, dies würde meine Leistung beeinträchtigen, da das Streamen unglaublich schnell sein müsste (15 Bilder pro Sekunde in den Speicher und aus dem Speicher) und obwohl die Bilder sehr klein wären, wäre es möglicherweise eine bessere Idee, Zeichenspritesheets zu laden stattdessen in den Speicher. Aber ich muss trotzdem ein Stream-ähnliches Rendering-System für ein einzelnes Bild für meinen größeren Boss-Charakter programmieren.
Ich habe experimentiert, aber es ist kein einfacher Prozess. Vor allem, weil ich an anderen Teilen der Spiel-Engine arbeite, die sich momentan nicht mit Grafik befassen.
Antworten:
Wir haben einen ähnlichen Fall mit unserem RTS Remake. Alle Einheiten und Häuser sind Sprites. Wir haben 18.000 Sprites für Einheiten und Häuser und Gelände sowie weitere ca. 6.000 für Teamfarben (angewendet als Masken). Lang gestreckt haben wir auch ungefähr 30 000 Zeichen, die in Schriften verwendet werden.
Der Hauptgrund für Atlanten sind also:
Was hat bei uns nicht geklappt:
Jetzt haben wir alles in Dutzenden von 1024x1024-Atlanten gepackt (moderne GPUs unterstützen sogar noch größere Dimensionen) und das funktioniert nur gut, wenn man nur ~ 300 MB Arbeitsspeicher isst, was für ein PC-Spiel ganz gut ist. Einige Optimierungen hatten wir:
Wenn Sie ernsthaft in Betracht ziehen, auf mobile Geräte zu wechseln, müssen Sie sich um Einschränkungen kümmern. Lassen Sie das Spiel erst einmal laufen und ziehen Sie die Spieler an! ;)
quelle
Ich habe eine tangential ähnliche Antwort in hier , aber die allgemeine Idee ist , dass, wenn Sie sich Laden und Zeichnen Texturen zu unterschiedlichen Zeiten (Sie nicht zusätzliche Texturen , während Sie Rendering - Laden), dann gibt es zwei Orte , wo , was Sie wird Ihre Leistung beeinträchtigen:
Ladezeit:
Dies ist der Moment, in dem Sie Ihre Texturen in den Speicher hochladen. Das ganze Datenmenge, die Sie an VRAM senden, bestimmt hauptsächlich, wie lange Ihre Ladezeit sein wird. Wenn Sie Ihre Texturen mit kleineren Formaten wie RGBA4444 versehen, wird dies schneller. Wenn Sie jedoch keine Texturen mit einer Größe von Hunderten von Megabyte in den VRAM hochladen, haben Sie hier wahrscheinlich keinen Engpass. Wenn Sie dies tun, kann ein netter Ladebildschirm das Warten erleichtern.
Das Zusammenfügen Ihrer Texturen zu Atlanten hat nur geringe Auswirkungen, da die gesamte Menge an Informationen, die Sie an VRAM senden, identisch ist. Wenn Sie Ihre Texturen atlasieren und Leerstellen in Ihren Atlanten belassen müssen, senden Sie tatsächlich mehr Daten in den VRAM, und daher ist dieser Teil langsamer!
Rendering-Leistung:
Sobald sich alle Ihre Texturen im VRAM befinden, hat die Anzahl der vorhandenen Texturen keinen Einfluss auf die Renderleistung. Es gibt vier Elemente, die sich auf die Renderleistung auswirken:
Statusänderungen rendern : Jedes Mal, wenn Sie das Bild ändern, von dem Sie rendern möchten, wird die zum Rendern erforderliche Zeit erheblich verlängert. Im Allgemeinen möchten Sie die Anzahl der Statusänderungen minimieren, und Sie können die Anzahl der Statusänderungen reduzieren, indem Sie mehrere Bilder, die Sie nacheinander zeichnen, zu einem Texturatlas zusammenfassen.
Nur atlasing ist nicht genug. Sie müssen so atlasieren, dass Zustandsänderungen reduziert werden, um Leistungszuwächse zu erzielen. Zum Beispiel könnte man meinen, dass ein Hauptcharakter in einem Sprite-Arbeitsblatt zu einem Leistungsgewinn führt. Wenn Sie jedoch nur ein Sprite von diesem Sprite-Arbeitsblatt pro Frame zeichnen, erhalten Sie im Vergleich zu diesem keine Leistungsgewinne jedes Sprite in einer separaten Datei.
Richtiges Atlasing ist nicht trivial, aber im Allgemeinen können Sie Sprites aus derselben Ebene sicher gruppieren. Zum Beispiel ist es eine vielversprechende Idee, alle GUI-Elemente in einem Sprite-Blatt zu haben, während das alphabetische Gruppieren von Monstern möglicherweise nicht der Fall ist.
Draw Calls: Im Allgemeinen möchten Sie Ihre Draw Calls auf ein Minimum beschränken. Als Faustregel gilt, dass Sie zwei Draw-Aufrufe zu einem Draw-Aufruf zusammenfassen können, wenn sich der Render-Status zwischen zwei Draw-Aufrufen nicht ändert. Für erweiterte Leistungssteigerungen können Sie beispielsweise 8 Textur-Sampler verwenden und Zeichnungsaufrufe für jeweils 8 Texturen gruppieren, sodass Sie die Texturen nur alle 8 Texturen ändern müssen.
Dreieckszahl: Je mehr Dreiecke Sie zeichnen, desto länger dauert das Zeichnen. In modernen Computern und für die meisten 2D-Spiele sind Sie jedoch weit davon entfernt, dies zu maximieren. Sie können sicher Hunderttausende von Sprites pro Frame zeichnen und trotzdem unglaublich gute Frameraten erzielen. Sie werden wahrscheinlich mehr an die CPU gebunden sein, wenn Sie extrem viele Sprites zeichnen, bevor Sie Probleme mit Ihrer GPU bekommen.
API-Einstellungen: Wenn Sie alles richtig machen und immer noch seltsam niedrige Frameraten erzielen, überprüfen Sie die Einstellungen, mit denen Sie Ihre Sprites zeichnen. Ich kenne SFML nicht, aber zum Beispiel in Direct3D 9 kann das Erstellen eines Vertex-Puffers mit
D3DUSAGE_DYNAMIC
oder inD3DPOOL_MANAGED
Ihre Renderzeiten leicht verzehnfachen. Wenn Sie vSync verwenden, wird Ihre Framerate natürlich auf die Aktualisierungsrate Ihres Monitors begrenzt. Die Verwendung nicht ausgerichteter FVFs kann bei einigen GPUs die Leistung beeinträchtigen. Auch dies gilt für Direct3D 9.Überprüfen Sie in Ihrem Fall die Dokumentation der von Ihnen verwendeten API.
Wenn Sie nur eine geringe bis mäßige Menge an Texturen haben (weniger als 1 GB) und nur eine geringe Menge an Sprites zeichnen (weniger als eine Million pro Frame), ist das erste, worauf ich achten würde, das Ändern der API-Einstellungen und Reduzieren Sie dann die Anzahl der Renderzustände und zeichnen Sie Aufrufe.
quelle