2012-08-14 8 views
5

Ich arbeite gerade an einem 2d Top-down RPG, geschrieben in Java 1.6 mit dem LWJGL. Ich habe die Verwendung von VBOs in mein Spiel implementiert und nun behalte ich zwei von ihnen: eins für Vertexdaten und eins für Texturkoordinaten.Aktualisierung von VBO-Daten mit glBufferSubData()

Es funktioniert alles gut, außer dass ich immer noch keine wirklich logische Möglichkeit habe, die Objekte zu aktualisieren. Wenn ich zum Beispiel möchte, dass eine bestimmte Kachel ihre Textur ändert (ändere die Texturkoordinaten in der VBO, um einen anderen Bereich der Textur anzuzeigen), kann ich keine Möglichkeit sehen, nur die entsprechenden Texturkoordinaten zu ändern diese einzelne Kachel. Alles, was ich mir vorstellen kann, ist vielleicht, die Puffer mit allen Daten zu füllen, die für jede Schleife benötigt werden, und sie mit glBufferData für jeden Frame hochzuladen. Es funktioniert, scheint aber nicht der beste Weg zu sein (oder tut es?).

Nun gibt es den Befehl glBufferSubData, der keinen neuen Speicher zuweist, sondern nur den Teil ändert, von dem ich sage, dass er geändert werden soll. Die Sache ist, ich weiß nicht, wie man den Bereich im Auge behält, der geändert werden muss (Offset). LWJGL bietet eine glBufferSubData (Ziel, Offset, Daten); Befehl, der nur den Anfang des Puffers benötigt, um zu arbeiten. Ist der Offset so etwas wie ein Index?

Also, wenn ich zum ersten Mal dieser Puffer auf die VBO laden und will dann den zweiten Wert des zweiten Schwimmers ändern []:

FloatBuffer vertexData = BufferUtils.createFloatBuffer(amountOfVertices * vertexSize); 
vertexData.put(new float[]{100, 100, 300, 100, 300, 300, 100, 300}); 
vertexData.put(new float[]{400, 100, 600, 100, 600, 300, 400, 300}); 
vertexData.flip(); 

Ich würde die neuen Daten erzeugt, lege es in einem kleinen FloatBuffer und Lade es mit glBufferSubData hoch (GL_VERTEX_ARRAY, 10, newFloatBuffer) ;? 10 ist, weil ich die Werte ab dem zehnten alten Wert ändern möchte.

Ist das richtig? Gibt es einen besseren Weg, es zu tun? Und noch einmal: Ist es in Ordnung, wenn ich die ganzen Daten jedes Frame neu hochlade?

+0

Es gibt einfachere Möglichkeiten, dies zu tun. Entweder zeichnen Sie einfach die gleiche Geometrie mit einer anderen Textur. Oder Sie ändern die Texturkoordinaten im Vertex-Shader. –

Antwort

6

LWJGL'sglBufferSubData() erwartet den Offset als Byteanzahl, da man beliebige Daten an beliebige Pufferspeicherorte schreiben kann. Wenn Sie die Float bei Index i aktualisieren möchten, wäre der Offset i * 4, da Java-Floats nehmen, die sehr häufig, 4 Bytes. Alle verbleibenden Pufferinhalte werden geschrieben, daher muss der Zielpuffer eine Kapazität von mindestens
(i + floatBuffer.remaining()) * 4 Bytes haben. Für die korrekte Vorbereitung, siehe Puffer flip() Methode oder position(int) zusammen mit limit(int) verwenden, um den restlichen Inhalt anzugeben, der geschrieben werden soll.

Diese Aktualisierungsstrategie ist in Ordnung, solange Sie glBufferSubData() nicht zu oft mit temporären FloatBuffers aufrufen. Sie könnten auch einen zweiten Zielpuffer mit der gleichen Größe für das Swapping (Ping Pong) haben, den Sie mit MapBuffer() für eine Gesamtaktualisierung zuordnen können, während der andere verwendet wird.

Ich würde lieber eine komplette FloatBuffer auf der Client-Seite halten und laden Sie es sofort mit glBufferData() anstatt glBufferSubData() oft aufrufen. Aber ohne einige Zahlen zu kennen, ist es schwer zu sagen.

+0

Vielen Dank. Ich werde die Client-FloatBuffer-Strategie implementieren und sie vorerst beibehalten. Später werde ich die Vertex-Shader ausprobieren. – Thiago

+0

Gern geschehen! Shader sind ein interessantes Gebiet. Wenn Sie Texturbereiche gleicher Größe ändern müssen, sind Array Texturen als Alternative zu einer Textur Map/Sheet möglich. 3D-Texturen könnten verwendet werden, um die Änderung zusätzlich sanft zu mischen. – Sam