O que é um buffer de índice e como ele está relacionado aos buffers de vértice?

11

Eu tenho um buffer de vértice como este:

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

Eu tenho o seguinte buffer de índice:

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

Eu sei que quero desenhar gl.LINESusando o WebGL, significa vários segmentos de linha separados.

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

Parece permitir o desenho de vários segmentos de linha em uma única chamada de desenho no WebGL.

Alguém poderia ELI5 para mim, o que é um buffer de índice e como ele está relacionado aos buffers de vértice? Como gerar buffers de índice a partir de minhas primitivas?

Afr
fonte

Respostas:

12

Alguém poderia ELI5 para mim, o que é um buffer de índice e como ele está relacionado aos buffers de vértice

Seu buffer de vértice contém as coordenadas X e Y de 5 vértices. Eles são:

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

Seu buffer de índice contém informações sobre quais linhas desenhar entre esses vértices. Ele usa o índice de cada vértice no buffer de vértice como um valor.

Como você está desenhando linhas, cada par de valores consecutivos no seu buffer de índice indica um segmento de linha. Por exemplo, se o buffer de índice começa com 0, 2, significa desenhar uma linha entre o 0º e o 2º vértices na matriz de vértices, que nesse caso desenharia uma linha que vai de [0.0, 0.0]para [0.0, 0.6].

No gráfico a seguir, cada par de índices é coordenado por cores com a linha que indica:

insira a descrição da imagem aqui

Da mesma forma, se você estivesse desenhando triângulos em vez de linhas, seria necessário fornecer um buffer de índice em que cada 3 valores consecutivos indiquem os índices de três vértices no buffer de vértice, por exemplo,

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

Se você possui um buffer de vértice 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
]

E simplesmente desenhe 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);

Exigiria duas coordenadas dedicadas para cada segmento de linha. Com o verticesdefinido acima, só seria possível desenhar duas linhas :

duas linhas

Se você tiver os seguintes índices definidos:

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

É possível desenhar linhas que cruzam os mesmos vértices repetidamente. Isso reduz a redundância. Se você vincular o buffer de índice e solicitar à GPU para desenhar segmentos de linha que conectam os vértices pela ordem especificada na matriz de indecies:

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

Pode-se desenhar figuras mais complexas sem redefinir os mesmos vértices repetidamente. Este é o resultado:

uma casa

Para alcançar o mesmo resultado sem índices, o buffer de vértice deve se parecer com o seguinte:

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

O que resulta na mesma imagem:

ainda outra casa

Observe a enorme redundância nos vértices armazenados.

Afr
fonte
2
Se você planeja responder imediatamente sua própria pergunta, pelo menos mencione-a na pergunta para que outras pessoas não percam seu tempo.
Rotem
2
Toda boa pergunta deve ter 2 ou 3 boas respostas. Você não perdeu seu tempo e eu realmente apreciei seus esforços. Preciso deste tópico para explicar a lógica a um parceiro de projeto e sua postagem o ajudará muito.
Afr
1
@ 5chdn A resposta automática é altamente incentivada . Obrigado por adicionar esta resposta. Se você tiver uma resposta em mente no momento em que postar uma pergunta, há uma caixa de seleção abaixo da pergunta que permitirá que você escreva sua resposta antes de postar a pergunta, para que ambos apareçam ao mesmo tempo. Isso é apenas para informá-lo, caso seja útil - você certamente não precisa fazer isso e as respostas automáticas ainda são muito bem-vindas a qualquer intervalo de tempo após a publicação da pergunta.
Trichoplax