Optimiertes 2D Tile Scrolling in OpenGL

8

Ich entwickle ein 2D-Sidescrolling-Spiel und ich muss meinen Tiling-Code optimieren, um eine bessere Bildrate zu erhalten. Im Moment verwende ich einen Texturatlas und 16x16 Kacheln für 480x320 Bildschirmauflösung. Die Ebene scrollt in beide Richtungen und ist deutlich größer als 1 Bildschirm (Tausende von Pixeln). Ich benutze glTranslate für das eigentliche Scrollen.

Bisher habe ich es versucht:

  • Zeichnen Sie nur die Kacheln auf dem Bildschirm mit glTriangles, 2 pro Quadratkachel (zu viel Overhead)
  • Zeichnen Sie die gesamte Karte als Anzeigeliste (groß auf einer kleinen Ebene, um eine große zu verlangsamen)

  • Partitionierung der Karte in die Anzeige Listet die halbe Bildschirmgröße auf und löscht dann die Anzeigelisten (bei 2-seitigem Scrolling wird die Geschwindigkeit immer noch verringert, Overdraw ist nicht effizient)

Jeder Rat wird geschätzt, aber vor allem frage ich mich:

  • Ich habe Vertex Arrays / VBOs dafür vorgeschlagen, weil sie dynamisch sind. Was ist der beste Weg, um davon zu profitieren? Wenn ich einfach einen Scheitelpunkt von Scheitelpunkten und ein bisschen Overdraw behalte, müsste ich das Array alle paar Frames neu kopieren, um die Änderung der relativen Koordinaten zu berücksichtigen (alles verschieben und die neuen Zeilen / Spalten hinzufügen). Wenn ich mehr Overdraw verwende, scheint das kein großer Gewinn zu sein. Es ist wie bei der Idee der Idee mit der Hälfte der Bildschirmdarstellung.
  • Gibt glScissor irgendeinen Gewinn, wenn es auf einer Menge kleiner Kacheln wie diesem verwendet wird, sei es eine Anzeigeliste oder ein Vertex-Array / VBO
  • Wäre es besser, nur aus großen Texturen die Ebene aufzubauen und dann glScissor zu verwenden? Würden die Speicherersparnisse beim Tiling für die mobile Entwicklung ein Problem darstellen, wenn ich das tue (nur neugierig, ich bin gerade auf einem PC)? Dieser Ansatz wurde hier erwähnt

Danke:)

    
user328517 29.04.2010, 05:50
quelle

1 Antwort

9

So würde ich eine schnelle 2D-Tile-Engine codieren:

Zuerst würde ich eine saubere Trennung zwischen dynamischen Kacheln (Zeichen, Elemente ..) und statischen (Ebene) machen.

Statische Kacheln:

Zum Zeichnen der statischen (Kacheln, die die gesamte Ebene aufbauen) verwende ich einen statischen Puffer (in einem Pufferobjekt gespeichert), der jede Kachelposition (x, y, Ebene) und einen Index für die Atlastextur enthält Daten (i). Da Ihr Texturatlas Kacheln mit fester Größe von 16x16 Pixeln enthält, können Sie die Vertex-Koordinaten für jeden Scheitelpunkt einfach berechnen.

Zum Zeichnen der Ebene würde ich einen einzelnen Zeichnungsaufruf (unter Verwendung der Instanzierung) eines Dreieckstreifens verwenden, der ein Viereck bildet, Eckendaten werden in einem statischen VBO (aus 4 Eckpunkten) und Indexdaten in einem statischen IBO (aus 4 Indizes), wobei pro Instanz Werte für das Vertex-Attribut im Vertex-Shader verwendet werden.

Dies würde Ihnen fast "freies" Kachel-Culling auf der GPU ermöglichen, da Clipping-Hardware sehr schnell ist. Selbst wenn Sie eine große Anzahl von Kacheln in Ihrem Level haben, sagen wir 30 * 20 (Kacheln / auf einem Bildschirm) und ungefähr ~ 50 Bildschirm / Level, würde es 30.000 Kacheln machen. Ich denke, es ist immer noch akzeptabel (auch auf Low-End-GPUs. Übrigens, zielen Sie auf iPhone / Android? Wenn ja, Instanziierung / Shadern sind nicht verfügbar für OpenGL ES 1.0 und OpenGL ES 2.0 hat keine Instanziierung Unterstützung, kann aber tun, Shader explodieren Kacheldaten in einem VBO / IBO und verwenden GL_TRIANGLES . Sie können weniger Daten explodieren und den GPU-Speicher entlasten, indem Sie Vertices-Attribute in einem Shader berechnen.

In jedem Fall sollten Sie die Texturkacheldaten nicht duplizieren und einen Texturatlas und einen VBO und IBO behalten.

Dynamische Kacheln:

Ich würde einen dynamischen VBO (und einen statischen IBO, der GL_TRIANGLES darstellt, also 0,1,2, 2,1,3, 0 + 4,1 + 4,2 + 4 ..) verwenden, die Kachelpositionen darstellen, Texturkoordinaten, Ebenen und aktualisiere sie mit sichtbaren dynamischen Kacheln in einem Bildschirm über glBufferSubData und zeichne diese Kacheln über glDrawElements .

Natürlich bedeutet dies, dass Sie eine maximale Anzahl an dynamischen Kacheln haben, die Sie pro glDrawElements zeichnen können. Wenn Sie also auf dieses Limit stoßen, müssen Sie das VBO erneut aktualisieren / zeichnen.

>

Wenn Ihre OpenGL-Implementierung keine Unterstützung für VBO / IBO bietet (wie in OpenGL ES 1.0), verwenden Sie stattdessen VA. Ich empfehle nicht die Verwendung von DL oder Sofort-Modus (keine Unterstützung für OpenGL ES).

Verwenden Sie schließlich glOrtho , um Ihre Kamera über die Ebene zu bewegen, zu vergrößern / verkleinern usw. Viel Glück!

    
Stringer 29.04.2010 16:24
quelle

Tags und Links