¿Qué es un búfer de índice y cómo se relaciona con los búferes de vértices?

11

Tengo un búfer de vértices como este:

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

Tengo el siguiente búfer de índice:

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

Sé que quiero dibujar gl.LINESusando WebGL, significa múltiples segmentos de línea separados.

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

Parece permitir el dibujo de múltiples segmentos de línea en una sola llamada de dibujo en WebGL.

¿Podría alguien ELI5 para mí, qué es un búfer de índice y cómo se relaciona con los búferes de vértices? ¿Cómo generar buffers de índice a partir de mis primitivas?

Afr
fuente

Respuestas:

12

¿Podría alguien ELI5 para mí, qué es un búfer de índice y cómo se relaciona con los búferes de vértices?

Su búfer de vértices contiene las coordenadas X e Y de 5 vértices. Son:

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

Su búfer de índice contiene información sobre qué líneas dibujar entre estos vértices. Utiliza el índice de cada vértice en el búfer de vértices como valor.

Como está dibujando líneas, cada par de valores consecutivos en su búfer de índice indica un segmento de línea. Por ejemplo, si el búfer de índice comienza con 0, 2, significa dibujar una línea entre los vértices 0º y 2º en la matriz de vértices, que en este caso dibujaría una línea que va de [0.0, 0.0]a [0.0, 0.6].

En el siguiente gráfico, cada par de índices tiene un color coordinado con la línea que indica:

ingrese la descripción de la imagen aquí

Del mismo modo, si estuviera dibujando triángulos en lugar de líneas, necesitaría proporcionar un búfer de índice donde cada 3 valores consecutivos indican los índices de tres vértices en el búfer de vértices, por ejemplo

0, 1, 2,
2, 1, 3,
2, 3, 4,
Rotem
fuente
5

Si tiene un búfer de vértices como este:

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
]

Y simplemente dibújalo como está:

// 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);

Requeriría dos coordenadas dedicadas para cada segmento de línea. Con lo verticesdefinido anteriormente, solo sería posible dibujar dos líneas :

dos lineas

Si tiene definidos los siguientes índices:

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

Es posible dibujar líneas que se cruzan con los mismos vértices una y otra vez. Esto reduce la redundancia. Si vincula el búfer de índice y le dice a la GPU que dibuje segmentos de línea que conectan los vértices por el orden especificado en la matriz de indencias:

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);

Uno puede dibujar figuras más complejas sin redefinir los mismos vértices una y otra vez. Este es el resultado:

una casa

Para lograr el mismo resultado sin índices, el búfer de vértices debería tener el siguiente aspecto:

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);

Lo que da como resultado la misma imagen:

otra casa

Tenga en cuenta la enorme redundancia en los vértices almacenados.

Afr
fuente
2
Si planea responder de inmediato a su propia pregunta, al menos menciónela en la pregunta para que otros no pierdan su tiempo.
Rotem
2
Toda buena pregunta debe tener 2 o 3 buenas respuestas. No perdiste el tiempo y realmente aprecié tus esfuerzos. Necesito este hilo para explicar la lógica a un socio del proyecto y su publicación lo ayudará mucho.
Afr
1
@ 5chdn La auto respuesta es altamente recomendable . Gracias por agregar esta respuesta. Si tiene una respuesta en mente al momento de publicar una pregunta, hay una casilla debajo de la pregunta que le permitirá escribir su respuesta antes de publicar la pregunta, por lo que ambas aparecerán al mismo tiempo. Esto es solo para hacerle saber en caso de que sea útil; ciertamente no necesita hacer esto y las respuestas personales son muy bienvenidas en cualquier intervalo de tiempo después de publicar la pregunta.
trichoplax