Was ist ein Indexpuffer und wie hängt er mit Scheitelpunktpuffern zusammen?


11

Ich habe einen Vertex-Puffer wie diesen:

0.0, 0.0,
1.0, 0.0,
0.0, 0.6,
1.0, 0.6,
0.5, 1.0

Ich habe folgenden Indexpuffer:

0, 2,
2, 4,
4, 3,
3, 2,
2, 1,
1, 0,
0, 3,
3, 1

Ich weiß, dass ich gl.LINESmit WebGL zeichnen möchte, dh mehrere getrennte Liniensegmente.

gl.drawElements(gl.LINES, 16, gl.UNSIGNED_SHORT, indexBuffer);

Es scheint das Zeichnen mehrerer Liniensegmente in einem einzigen Zeichenaufruf in WebGL zu ermöglichen.

Könnte mir jemand ELI5, was ist ein Indexpuffer und wie hängt er mit Vertex-Puffern zusammen? Wie generiere ich Indexpuffer aus meinen Grundelementen?

Antworten:


12

Könnte mir jemand ELI5 geben, was ein Indexpuffer ist und wie er mit Vertex-Puffern zusammenhängt

Ihr Scheitelpunktpuffer enthält die X- und Y-Koordinaten von 5 Scheitelpunkten. Sie sind:

index |  X  |  Y
  0   | 0.0 | 0.0 
  1   | 1.0 | 0.0
  2   | 0.0 | 0.6
  3   | 1.0 | 0.6
  4   | 0.5 | 1.0

Ihr Indexpuffer enthält Informationen darüber, welche Linien zwischen diesen Scheitelpunkten gezogen werden sollen. Es verwendet den Index jedes Scheitelpunkts im Scheitelpunktpuffer als Wert.

Da Sie Linien zeichnen, gibt jedes Paar aufeinanderfolgender Werte in Ihrem Indexpuffer ein Liniensegment an. Wenn der Indexpuffer beispielsweise mit beginnt 0, 2, bedeutet dies, dass eine Linie zwischen dem 0. und 2. Scheitelpunkt im Scheitelpunktarray gezeichnet wird, die in diesem Fall eine Linie von [0.0, 0.0]bis zeichnen würde [0.0, 0.6].

In der folgenden Grafik ist jedes Indexpaar farblich auf die angezeigte Linie abgestimmt:

Geben Sie hier die Bildbeschreibung ein

Wenn Sie Dreiecke anstelle von Linien zeichnen würden, müssten Sie einen Indexpuffer angeben, in dem jeweils 3 aufeinanderfolgende Werte die Indizes von drei Scheitelpunkten im Scheitelpunktpuffer angeben, z

0, 1, 2,
2, 1, 3,
2, 3, 4,

5

Wenn Sie einen Scheitelpunktpuffer wie diesen haben:

var vertices = [
  0.0, 0.0, 0.0,
  1.0, 0.0, 0.0,
  0.0, 0.6, 0.0,
  1.0, 0.6, 0.0,
  0.5, 1.0, 0.0
]

Und zeichnen Sie es einfach so wie es ist:

// Create an empty buffer object
var vertex_buffer = gl.createBuffer();

// Bind appropriate array buffer to it
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);

// Pass the vertex data to the buffer
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

/* [...] */

// Draw the lines
gl.drawArrays(gl.LINES, 0, 5);

Es würde zwei dedizierte Koordinaten für jedes Liniensegment erfordern. Mit der verticesoben definierten wäre es nur möglich, zwei Linien zu zeichnen :

zwei Linien

Wenn Sie folgende Indizes definiert haben:

var indices = [
  0, 2,
  2, 4,
  4, 3,
  3, 2,
  2, 1,
  1, 0,
  0, 3,
  3, 1
]

Es ist möglich, Linien zu zeichnen, die immer wieder dieselben Eckpunkte schneiden. Dies reduziert die Redundanz. Wenn Sie den Indexpuffer binden und die GPU anweisen, Liniensegmente zu zeichnen, die die Eckpunkte in der im Indecies-Array angegebenen Reihenfolge verbinden:

var index_buffer = gl.createBuffer();

gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);

gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);

// draw geometry lines by indices
gl.drawElements(gl.LINES, 16, gl.UNSIGNED_SHORT, index_buffer);

Man kann komplexere Figuren zeichnen, ohne dieselben Eckpunkte immer wieder neu zu definieren. Das ist das Ergebnis:

ein Haus

Um das gleiche Ergebnis ohne Indizes zu erzielen, sollte der Scheitelpunktpuffer wie folgt aussehen:

var vertices = [
  0.0, 0.0, 0.0,
  0.0, 0.6, 0.0,
  0.0, 0.6, 0.0,
  0.5, 1.0, 0.0,
  0.5, 1.0, 0.0,
  1.0, 0.6, 0.0,
  1.0, 0.6, 0.0,
  0.0, 0.6, 0.0,
  0.0, 0.6, 0.0,
  1.0, 0.0, 0.0,
  1.0, 0.0, 0.0,
  0.0, 0.0, 0.0,
  0.0, 0.0, 0.0,
  1.0, 0.6, 0.0,
  1.0, 0.6, 0.0,
  1.0, 0.0, 0.0
]

/* [...] */

// Draw the lines
gl.drawArrays(gl.LINES, 0, 16);

Was zu demselben Bild führt:

noch ein Haus

Beachten Sie die enorme Redundanz in gespeicherten Scheitelpunkten.


2
Wenn Sie vorhaben, Ihre eigene Frage sofort zu beantworten, erwähnen Sie sie bitte zumindest in der Frage, damit andere ihre Zeit nicht verschwenden.
Rotem

2
Jede gute Frage sollte 2 oder 3 gute Antworten haben. Sie haben Ihre Zeit nicht verschwendet und ich habe Ihre Bemühungen sehr geschätzt. Ich brauche diesen Thread, um einem Projektpartner die Logik zu erklären, und Ihr Beitrag wird ihm sehr helfen.
Afr

1
@ 5chdn Selbstantworten wird dringend empfohlen . Vielen Dank für das Hinzufügen dieser Antwort. Wenn Sie zum Zeitpunkt der Veröffentlichung einer Frage eine Antwort im Sinn haben, befindet sich unter der Frage ein Kontrollkästchen, mit dem Sie Ihre Antwort schreiben können, bevor Sie die Frage stellen, sodass beide gleichzeitig angezeigt werden. Dies dient nur dazu, Sie zu informieren, falls es nützlich ist - Sie müssen dies sicherlich nicht tun, und Selbstantworten sind nach dem Posten der Frage in jedem Zeitraum sehr willkommen.
Trichoplax
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.