Der schnellste Weg, Quads in OpenGL ES zu zeichnen?

21

Ich benutze OpenGL ES 2.0. Ich habe ein paar Quads zu zeichnen, würde gerne nur 4 Eckpunkte pro Quad übergeben müssen, als würde ich GL_QUADS verwenden, aber im Grunde möchte ich nur wissen, wie man a am besten zeichnet Haufen von separaten Quads.

Bisher konnte ich Folgendes tun: -GL_TRIANGLES (6 Eckpunkte pro Quad) -Degenerate GL_TRIANGLE_STRIP (6 Eckpunkte pro Quad)

Möglichkeiten, die ich gefunden habe: -GL_TRIANGLE_STRIPS mit einem speziellen Indexwert, der den Quad-Strip zurücksetzt (dies würde 5 Indizes pro Quad bedeuten, aber ich denke nicht, dass dies möglich ist, ist OpenGL ES 2.0)

Jonathan
quelle

Antworten:

33

Verwenden Sie einfach den Indexpuffer und GL_TRIANGLES. In diesem Fall benötigen Sie 4 Eckpunkte + 6 Indizes pro Quad (6 zusätzliche Indizes klingen möglicherweise übermäßig, aber in Wirklichkeit ist dies nicht der Fall - sobald Sie Ihren Indexpuffer erstellt haben, müssen Sie ihn nicht erneut berühren). Weitere Informationen finden Sie auf dieser Seite (Suche nach glDrawElements).

Einfacher Beispielcode:

GLfloat vertices[] = {-1, -1, 0, // bottom left corner
                      -1,  1, 0, // top left corner
                       1,  1, 0, // top right corner
                       1, -1, 0}; // bottom right corner

GLubyte indices[] = {0,1,2, // first triangle (bottom left - top left - top right)
                     0,2,3}; // second triangle (bottom left - top right - bottom right)

glVertexPointer(3, GL_FLOAT, 0, vertices);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices);

Wenn Sie nur ein Quad zeichnen, benötigen Sie nur 4 Eckpunkte, um es mit Dreiecksstreifen zu zeichnen ( wie in Wikipedia gezeigt ), aber ich denke, Sie haben das bereits gewusst.

user4241
quelle
Der traditionelle Trick zum Zusammenführen mehrerer Dreiecksstreifen zu einem einzigen Streifen ist "degenerierte Dreiecke": Wenn Sie das letzte Element eines Streifens und das erste Element des nächsten Streifens wiederholen, werden 2 Dreiecke mit einer Fläche von Null erstellt, die also nichts zeichnen. Betrachten Sie die zweiten Quad-Indizes (4, 5, 6, 7). Der Indexpuffer für GL_TRIANGLE_STRIP von zwei Quads könnte sein: {0, 1, 2, 3, 3, 4,4, 5, 6, 7}. Die entarteten Dreiecke sind 3,3,4und 3,4,4. Lohnt es sich das zu tun? Nein, es sei denn, Ihre Quads kommen in der Regel paarweise (oder mehr) mit gemeinsamen Kanten. Wenn das 2. Quad {3, 2, 4, 5} ist, ist Strip {0,1,3,2,5,4}.
ToolmakerSteve
8
Und um dies jedem klar zu machen, der vorbeikommt und ein paar Quads zeichnen muss: Kopieren Sie aus Performancegründen den obigen Code NICHT und erstellen Sie ein glDrawElements, das ONCE FOR EACH QUAD aufruft . Bauen Sie stattdessen EIN Scheitelpunkt-Array und EIN Index-Array auf, das ALLE Quads enthält, die Sie zeichnen möchten. Mit GL_TRIANGLES könnten zwei Quads Indizes haben {0,1,2, 0,2,3, 4,5,6, 4,6,7}oder gleich gut sind {0,1,2, 2,3,0, 4,5,6, 6,7,4}. Gute Klasse dabei zu helfen ist glText-Android / Spritebatch
ToolmakerSteve
6

Index - Puffer zu verwenden ist nicht unbedingt schneller, wie in der Apple - Dokumentation angegeben, „Für die beste Leistung, Ihre Modelle sollten als ein einzigen unindexed Dreiecksstreifen vorgelegt werden mit glDrawArrays“ .

So, während ein GL_TRIANGLE_STRIPin vier Ecken tun , ohne einen Indexpuffer benötigt, und Sie können einen Index - Puffer verwenden, ist es ziemlich lahm zu „retten“ zu wiederholen , um zu versuchen 2 Ecken . Aus diesem Grund würde ich vorschlagen, dass Sie 2 separate Punkte zeichnen GL_TRIANGLESund die 2 Eckpunkte auf der Diagonale wiederholen .

Bobobobo
quelle
8
Ähm, nein. In diesem Dokument heißt es, dass Ihre Modelle als ein einziger INDEXIERTER Dreiecksstreifen eingereicht werden. Der nächste Satz lautet: "Um zu vermeiden, dass Daten für denselben Scheitelpunkt mehrmals im Scheitelpunktpuffer angegeben werden, verwenden Sie einen separaten Indexpuffer und zeichnen Sie den Dreiecksstreifen mit der Funktion glDrawElements." Welches ist genau das, was Sie entschieden haben, war "lahm".
Davidf2281
3
Da der doc-Absatz jetzt auf glDrawElements und nicht auf glDrawArrays verweist, wurde er wahrscheinlich seit dieser Antwort neu geschrieben. Der Punkt, den der Doc ansprach, war jedoch, dass er für die Leistung einen einzelnen Strip bereitstellte (anstatt mehrere Strips, daher mehrere gl-Aufrufe). In dieser Situation glaube ich, dass der Unterschied zwischen der Verwendung von Indizes oder nicht unbedeutend ist ; Es kommt darauf an, alles in ein einzelnes Vertex-Array (plus ein optionales Index-Array) zu packen, damit Sie einen einzelnen gl-Aufruf durchführen können.
ToolmakerSteve
0

Der große Vorteil des Desktops besteht darin, die Daten in GL_STATIC_DRAW-VBOs zu verschieben. Vermutlich trifft dies auch auf die MBX-GPU des iPhones zu.

Wille
quelle
-2

Bei Verwendung GL_TRIANGLE_FANfür ein Quad werden 4 Scheitelpunkte verwendet, nicht 6.

Mr. Blah
quelle
Ja, aber das tut es auch GL_TRIANGLE_STRIP , wie andere Antworten bereits gezeigt haben.
Anko
@Herr. Blah - Sie haben den Punkt der Frage verpasst, wie man effizient ein paar Quads macht. Man sollte nicht für jedes Quad einen gl-Aufruf machen, sondern viele Quads zu einem einzigen Array zusammenfassen, das mit einem einzigen gl-Aufruf gezeichnet werden kann. GL_TRIANGLE_FAN hilft hier nicht weiter und ist daher beim Rendern mit hoher Leistung selten hilfreich.
ToolmakerSteve