Frage

Ich versuche eine klare Vorstellung davon zu bekommen, wann ich indizierte Arrays von OpenGL -Scheitelpunkten verwenden soll, die mit GL [Multi] Drawelements und dergleichen gezeichnet werden, gegenüber wann ich einfach zusammenhängende Arrays von Scheitelpunkten verwenden sollte, gezeichnet mit GL [Multi] Drawarrays .

(Aktualisieren: Der Konsens in den Antworten, die ich habe, ist, dass man immer indizierte Eckpunkte verwenden sollte.)

Ich bin in diesem Thema mehrmals hin und her gegangen, also werde ich mein aktuelles Verständnis beschreiben, in der Hoffnung, dass mir jemand entweder sagen kann, dass ich jetzt endlich mehr oder weniger korrekt bin, oder darauf hinweisen, wo meine verbleibenden Missverständnisse sind . Insbesondere habe ich drei Schlussfolgerungen, fett. Bitte korrigieren Sie sie, wenn sie falsch liegen.

Ein einfacher Fall ist, wenn meine Geometrie aus Maschen besteht, um gekrümmte Oberflächen zu bilden. In diesem Fall haben die Scheitelpunkte in der Mitte des Netzes identische Attribute (Position, Normal, Farbe, Texturkoordung usw.) für jedes Dreieck, das den Scheitelpunkt verwendet.

Dies führt mich zu dem Schluss:

1. Für die Geometrie mit wenigen Nähten sind indizierte Arrays ein großer Gewinn.

Folgen Sie Regel 1 immer, außer:

Für die Geometrie, die sehr "blockig" ist, bei denen jede Kante eine Naht darstellt, ist der Nutzen indexierten Arrays weniger offensichtlich. Um einen einfachen Würfel als Beispiel zu nehmen, obwohl jeder Scheitelpunkt in drei verschiedenen Gesichtern verwendet wird, können wir keine Scheitelpunkte zwischen ihnen teilen, da für einen einzelnen Scheitelpunkt die Oberflächennormalen (und mögliche andere Dinge wie Farbe und Texturkoord ) unterscheidet sich in jedem Gesicht. Daher müssen wir explizit redundante Scheitelpunktpositionen in unser Array einführen, damit die gleiche Position mehrmals mit unterschiedlichen Normalen usw. verwendet werden kann. Dies bedeutet, dass indexierte Arrays weniger nützlich sind.

zB beim Rendern eines einzelnen Gesichts eines Würfels:

 0     1
  o---o
  |\  |
  | \ |
  |  \|
  o---o
 3     2

(Dies kann isoliert berücksichtigt werden, da die Nähte zwischen diesem Gesicht und allen benachbarten Gesichtern mittlerer als keiner dieser Scheitelpunkte zwischen den Gesichtern geteilt werden können)

Wenn Sie mit GL_Triangle_fan (oder _strip) rendern, kann jedes Gesicht des Würfels daher gerendert werden:

verts  = [v0, v1, v2, v3]
colors = [c0, c0, c0, c0]
normal = [n0, n0, n0, n0]

Durch das Hinzufügen von Indizes können wir dies nicht vereinfachen.

Daraus schließe ich:

2. Wenn Sie Geometrie rendern, die alle Nähte oder meist Nähte sind, sollte ich bei Verwendung von GL_Triangle_strip oder _fan niemals indizierte Arrays verwenden und stattdessen immer GL [multi] drawarrays verwenden.

(Aktualisieren: Antworten zeigen, dass diese Schlussfolgerung falsch ist. Auch wenn Indizes es uns nicht erlauben, die Größe der Arrays hier zu reduzieren, sollten sie aufgrund anderer Leistungsvorteile verwendet werden, wie in den Kommentaren erläutert).

Die einzige Ausnahme von Regel 2 ist:

Bei Verwendung von GL_TRIANGLES (anstelle von Streifen oder Lüftern) kann die Hälfte der Eckpunkte immer noch zweimal mit identischen Normalen und Farben usw. wiederverwendet werden, da jedes Würfelflächen als zwei separate Dreiecke gerendert wird. Wieder für das gleiche einzelne Würfelgesicht:

 0     1
  o---o
  |\  |
  | \ |
  |  \|
  o---o
 3     2

Ohne Indizes wären die Arrays mit GL_TRIANGLES so etwas wie:

verts =   [v0, v1, v2,  v2, v3, v0]
normals = [n0, n0, n0,  n0, n0, n0]
colors =  [c0, c0, c0,  c0, c0, c0]

Da ein Scheitelpunkt und ein Normalwert oft 3 Schwimmer sind und eine Farbe oft 3 Bytes beträgt, die für jedes Würfelgesicht über:

verts   = 6 * 3 floats = 18 floats
normals = 6 * 3 floats = 18 floats
colors  = 6 * 3 bytes  = 18 bytes

= 36 floats and 18 bytes per cube face.

(Ich verstehe, dass sich die Anzahl der Bytes ändern kann, wenn verschiedene Typen verwendet werden. Die genauen Abbildungen dienen nur zur Illustration.)

Mit Indizes können wir dies ein wenig vereinfachen und geben:

verts   = [v0, v1, v2, v3]     (4 * 3 = 12 floats)
normals = [n0, n0, n0, n0]     (4 * 3 = 12 floats)
colors  = [c0, c0, c0, c0]     (4 * 3 = 12 bytes)
indices = [0, 1, 2,  2, 3, 0]  (6 shorts)

= 24 floats + 12 bytes, and maybe 6 shorts, per cube face.

Sehen Sie, wie im letzteren Fall die Scheitelpunkte 0 und 2 zweimal verwendet werden, jedoch nur einmal in jedem der Verts, Normalen und Farbenarrays dargestellt werden. Dies klingt nach einem kleinen Sieg für die Verwendung von Indizes, selbst im Extremfall jeder einzelnen Geometriekante eine Naht.

Dies führt mich zu dem Schluss:

3. Bei Verwendung von GL_TRIANGLES sollte man immer indizierte Arrays verwenden, selbst für Geometrie, die alle Nähte sind.

Bitte korrigieren Sie meine Schlussfolgerungen fett, wenn sie falsch liegen.

War es hilfreich?

Lösung

Daraus schließe ich, dass bei der Rendern von Geometrie, die alle Nähte oder meist Nähte sind, bei Verwendung von GL_TRIANGLE_STRIP oder _FAN niemals indexierte Arrays verwenden und stattdessen immer GL [Multi] Drawarrays verwenden sollte.

Nein, der Grund ist recht einfach.

Ihre Schlussfolgerung basiert auf der Tatsache, dass Sie ein einzelnes Quad analysiert haben, das aus zwei Dreiecken besteht. Diese beiden mit Dreieckslüfchen/Streifen gezogenen Dreiecke können mit indizierten Arrays nicht vereinfacht werden.

Aber versuchen Sie, über eine große Geländegeometrie nachzudenken. Jeder Geländeblock wird als Quad unter Verwendung von Dreieck -Lüfter/Streifen primitiv gezeichnet. Zum Beispiel:

Jeder Dreieck -Streifen in der Abbildung hat gemeinsam alle Scheitelpunkte mit benachbarten Dreiecksstreifen und ermöglicht die Verwendung von Indizes die Geometriedefinition, anstatt Scheitelpunkte für jeden Dreieck -Streifen zu wiederholen.


Grundsätzlich sind das Zeichnen von Primitiven (Dreiecke, Lüfter und Streifen), die Indizes verwenden, nützlich, wenn Sie die meisten Scheitelpunkte eines einzelnen Primitiven mit einem anderen teilen können.

Wenn Sie die Informationen teilen, können Sie die Bandbreite der Informationsübertragung speichern, ist jedoch nicht der einzige Vorteil. Tatsächlich erlauben indizierte Arrays:

  • Vermeiden Sie die Synchronisation der Informationen, die zu demselben "konzeptuellen" Scheitelpunkt gehören, der viele Male angegeben ist
  • Erlauben Sie, denselben Shader -Betrieb auf einem einzelnen Scheitelpunkt auszuführen, statt für jede Scheitelpunkt -Duplikation ein Vielfaches.
  • Die Kombination der Verwendung von Dreiecksstreifen/Lüfter und Indizes ermöglicht es der Anwendung, den Indizespuffer zu komprimieren, da die Streifen-/Lüfterspezifikation weniger Indizes erfordert (für jedes Gesicht ist für jedes Gesicht immer 3 Indizes erforderlich).

Das indizierte Array kann nicht verwendet werden, wie Sie angegeben haben, wenn ein Scheitelpunkt nicht alle damit verbundenen Informationen (Farbe, Texturkoordnungen usw.) mit einem anderen zusammenfälligen Scheitelpunkt teilen kann.


Der Vollständigkeitsgröße ist die Größe der für die Geometriespezifikation erforderlichen Informationen nicht der einzige Faktor, der den optimalen Rendering -Betrieb bestimmen.

Tatsächlich ist ein weiterer grundlegender Faktor für das primitive Rendering die Cache -Lokalisierung der Daten. Schlecht angegebene Geometriedaten (nicht verschachtelte Pufferobjekte, lange Dreiecksstreifen ...) verursachen viele Cache -Missen, abbauende Grafikkartenleistung.

Um den Rendering -Vorgang zu optimieren, muss die Scheitelpunktspezifikation mit der größten Wahrscheinlichkeit neu angeordnet werden, um zuvor angegebene Scheitelpunkte wiederzuverwenden. Auf diese Weise kann die Grafikkarten -Cache -Linie zuvor angegebene Scheitelpunkte wiederverwenden, ohne sie aus dem Speicher abzurufen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top