Wie lösen wir große Anforderungen an den Videospeicher in einem 2D-Spiel?
Wir entwickeln ein 2D-Spiel (Factorio) in Allegro C / C ++ und stehen vor dem Problem, dass die Anforderungen an den Videospeicher mit zunehmendem Spielinhalt steigen.
Wir sammeln derzeit alle Informationen zu Bildern, die zuerst verwendet werden sollen, beschneiden alle diese Bilder so weit wie möglich und ordnen sie so eng wie möglich in großen Atlanten an. Diese Atlanten werden im Videospeicher gespeichert, dessen Größe von den Systembeschränkungen abhängt. Derzeit sind es in der Regel 2 Bilder mit einer Größe von bis zu 8192 x 8192, sodass 256 MB bis 512 MB Videospeicher erforderlich sind.
Dieses System funktioniert ziemlich gut für uns, da wir mit einigen benutzerdefinierten Optimierungen und der Aufteilung des Render- und Update-Threads in der Lage sind, Zehntausende von Bildern auf dem Bildschirm mit 60 fps zu zeichnen. Wir haben viele Objekte auf dem Bildschirm, und das Ermöglichen einer großen Verkleinerung ist eine wichtige Voraussetzung. Da wir noch mehr hinzufügen möchten, wird es einige Probleme mit den Anforderungen an den Videospeicher geben, so dass dieses System möglicherweise nicht aushält.
Eines der Dinge, die wir versuchen wollten, ist ein Atlas mit den häufigsten Bildern und der zweite als Cache. Die Bilder würden bei Bedarf aus der Speicher-Bitmap dorthin verschoben. Bei diesem Ansatz gibt es zwei Probleme:
- Das Zeichnen von Speicher-Bitmap zu Video-Bitmap ist in Allegro schmerzhaft langsam.
- Es ist nicht möglich, mit einer anderen Video-Bitmap als dem Haupt-Thread in Allegro zu arbeiten, daher ist dies praktisch unbrauchbar.
Hier sind einige zusätzliche Anforderungen, die wir haben:
- Das Spiel muss deterministisch sein, damit die Leistungsprobleme / Ladezeiten den Spielstatus niemals ändern können.
- Das Spiel ist in Echtzeit und bald auch im Mehrspielermodus. Wir müssen um jeden Preis das kleinste Ruckeln vermeiden.
- Der Großteil des Spiels ist eine durchgehende offene Welt.
Der Test bestand aus dem Zeichnen von 10 000 Sprites in einem Stapel für Größen von 1x1 bis 300x300, mehrmals für jede Konfiguration. Ich habe die Tests mit der Nvidia Geforce GTX 760 durchgeführt.
- Das Zeichnen von Video-Bitmaps zu Video-Bitmaps nahm 0,1us pro Sprite in Anspruch, wenn sich die Quell-Bitmap nicht zwischen einzelnen Bitmaps änderte (die Atlas-Variante). Die Größe spielte keine Rolle
- Das Zeichnen von Video-Bitmaps in Video-Bitmaps nahm, während die Quell-Bitmaps zwischen Zeichnungen umgeschaltet wurden (Nicht-Atlas-Variante), 0,56 us pro Sprite in Anspruch. Auch die Größe spielte keine Rolle.
- Das Zeichnen von Speicherbitmaps auf Videobitmaps war wirklich verdächtig. Größen von 1x1 bis 200x200 brauchten 0,3us pro Bitmap, also nicht so schrecklich langsam. Bei größeren Formaten begann sich die Zeit sehr dramatisch zu erhöhen, und zwar bei 9us für 201x201 auf 3116us für 291x291.
Durch die Verwendung von Atlas wird die Leistung um einen Faktor größer als 5 erhöht. Wenn ich 10 ms für das Rendern hatte, bin ich mit einem Atlas auf 100.000 Sprites pro Frame und ohne diesen auf 20.000 Sprites beschränkt. Das wäre problematisch.
Ich habe auch versucht, eine Möglichkeit zum Testen der Bitmap-Komprimierung und des 1bpp-Bitmap-Formats für Schatten zu finden, aber ich konnte in Allegro keine Möglichkeit finden, dies zu tun.