WebGL - Geometria

Depois de obter o contexto WebGL, você deve definir a geometria do primitivo (objeto que deseja desenhar) e armazená-lo. No WebGL, definimos os detalhes de uma geometria - por exemplo, vértices, índices, cor da primitiva - usando matrizes JavaScript. Para passar esses detalhes aos programas shader, temos que criar os objetos de buffer e armazenar (anexar) os arrays JavaScript que contêm os dados nos respectivos buffers.

Note: Posteriormente, esses objetos de buffer serão associados aos atributos do programa de sombreador (vertex shader).

Definindo a geometria necessária

Um modelo 2D ou 3D desenhado usando vértices é chamado de mesh. Cada faceta em uma malha é chamada depolygon e um polígono é feito de 3 ou mais vértices.

Para desenhar modelos no contexto de renderização WebGL, você deve definir os vértices e índices usando matrizes JavaScript. Por exemplo, se quisermos criar um triângulo que se encontra nas coordenadas {(5,5), (-5,5), (-5, -5)} conforme mostrado no diagrama, então você pode criar uma matriz para os vértices como -

var vertices = [
   0.5,0.5,    //Vertex 1
   0.5,-0.5,   //Vertex 2
   -0.5,-0.5,  //Vertex 3
];

Da mesma forma, você pode criar uma matriz para os índices. Os índices para os índices triangulares acima serão [0, 1, 2] e podem ser definidos como -

var indices = [ 0,1,2 ]

Para uma melhor compreensão dos índices, considere modelos mais complexos como o quadrado. Podemos representar um quadrado como um conjunto de dois triângulos. Se (0,3,1) e (3,1,2) são os dois triângulos com os quais pretendemos desenhar um quadrado, então os índices serão definidos como -

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

Note -

Para primitivas de desenho, o WebGL fornece os dois métodos a seguir -

  • drawArrays() - Ao usar este método, passamos os vértices da primitiva usando matrizes JavaScript.

  • drawElements() - Ao usar este método, passamos vértices e índices da primitiva usando o array JavaScript.

Objetos Buffer

Um objeto buffer é um mecanismo fornecido pelo WebGL que indica uma área de memória alocada no sistema. Nestes objetos de buffer, você pode armazenar dados do modelo que deseja desenhar, correspondendo a vértices, índices, cor, etc.

Usando esses objetos de buffer, você pode passar vários dados para o programa de sombreador (sombreador de vértice) por meio de uma de suas variáveis ​​de atributo. Como esses objetos de buffer residem na memória da GPU, eles podem ser renderizados diretamente, o que, por sua vez, melhora o desempenho.

Para processar geometria, existem dois tipos de objetos de buffer. Eles são -

  • Vertex buffer object (VBO)- Ele contém os dados por vértice do modelo gráfico que será renderizado. Usamos objetos de buffer de vértice em WebGL para armazenar e processar os dados relativos aos vértices, como coordenadas de vértices, normais, cores e coordenadas de textura.

  • Index buffer objects (IBO) - Contém os índices (dados de índice) do modelo gráfico que será renderizado.

Depois de definir a geometria necessária e armazená-la em matrizes JavaScript, você precisa passar essas matrizes para os objetos de buffer, de onde os dados serão passados ​​para os programas de sombreador. As etapas a seguir devem ser seguidas para armazenar dados nos buffers.

  • Crie um buffer vazio.

  • Vincule um objeto de array apropriado ao buffer vazio.

  • Passe os dados (vértices / índices) para o buffer usando um dos typed arrays.

  • Desvincule o buffer (opcional).

Criando um Buffer

Para criar um objeto de buffer vazio, o WebGL fornece um método chamado createBuffer(). Este método retorna um objeto buffer recém-criado, se a criação foi bem-sucedida; caso contrário, ele retorna um valor nulo em caso de falha.

WebGL opera como uma máquina de estado. Depois que um buffer é criado, qualquer operação de buffer subsequente será executada no buffer atual até que o desviemos. Use o seguinte código para criar um buffer -

var vertex_buffer = gl.createBuffer();

Note - gl é a variável de referência para o contexto WebGL atual.

Ligar o Buffer

Depois de criar um objeto de buffer vazio, você precisa vincular um buffer de array apropriado (destino) a ele. WebGL fornece um método chamadobindBuffer() para este propósito.

Sintaxe

A sintaxe de bindBuffer() método é o seguinte -

void bindBuffer (enum target, Object buffer)

Este método aceita dois parâmetros e eles são discutidos a seguir.

target- A primeira variável é um valor enum que representa o tipo de buffer que queremos vincular ao buffer vazio. Você tem dois valores enum predefinidos como opções para este parâmetro. Eles são -

  • ARRAY_BUFFER que representa os dados do vértice.

  • ELEMENT_ARRAY_BUFFER que representa os dados do índice.

Object buffer- A segunda é a variável de referência para o objeto buffer criado na etapa anterior. A variável de referência pode ser de um objeto de buffer de vértice ou de um objeto de buffer de índice.

Exemplo

O fragmento de código a seguir mostra como usar o método bindBuffer ().

//vertex buffer
var vertex_buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);

//Index buffer
var Index_Buffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);

Passando dados para o buffer

O próximo passo é passar os dados (vértices / índices) para o buffer. Até agora, os dados estão na forma de um array e antes de passá-los para o buffer, precisamos envolvê-los em um dos arrays do tipo WebGL. WebGL fornece um método chamadobufferData() para este propósito.

Sintaxe

A sintaxe do método bufferData () é a seguinte -

void bufferData (enum target, Object data, enum usage)

Este método aceita três parâmetros e eles são discutidos abaixo -

target - O primeiro parâmetro é um valor enum que representa o tipo de buffer de matriz que usamos. As opções para este parâmetro são -

  • ARRAY_BUFFER que representa vertex data.

  • ELEMENT_ARRAY_BUFFER que representa index data.

Object data- O segundo parâmetro é o valor do objeto que contém os dados a serem gravados no objeto buffer. Aqui temos que passar os dados usandotyped arrays.

Usage- O terceiro parâmetro desse método é uma variável enum que especifica como usar os dados do objeto de buffer (dados armazenados) para desenhar formas. Existem três opções para este parâmetro, conforme listado abaixo.

  • gl.STATIC_DRAW - Os dados serão especificados uma vez e usados ​​muitas vezes.

  • gl.STREAM_DRAW - Os dados serão especificados uma vez e usados ​​algumas vezes.

  • gl.DYNAMIC_DRAW - Os dados serão especificados repetidamente e usados ​​muitas vezes.

Exemplo

O seguinte snippet de código mostra como usar o bufferData()método. Suponha que os vértices e índices são as matrizes que contêm os dados do vértice e do índice, respectivamente.

//vertex buffer
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

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

Matrizes digitadas

WebGL fornece um tipo especial de array chamado typed arrayspara transferir os elementos de dados, como vértice de índice e textura. Essas matrizes digitadas armazenam grandes quantidades de dados e os processam em formato binário nativo, o que resulta em melhor desempenho. Os arrays digitados usados ​​pelo WebGL são Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, UInt32Array, Float32Array e Float64Array.

Note

  • Geralmente, para armazenar dados de vértice, usamos Float32Array; e para armazenar dados de índice, usamosUint16Array.

  • Você pode criar matrizes digitadas assim como matrizes de JavaScript usando new palavra-chave.

Desvincular os Buffers

É recomendado que você desassocie os buffers após usá-los. Isso pode ser feito passando um valor nulo no lugar do objeto buffer, conforme mostrado abaixo.

gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);

WebGL fornece os seguintes métodos para realizar operações de buffer -

Sr. Não. Métodos e Descrição
1

vazio bindBuffer(enum target , Object buffer )

alvo - ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER

2

vazio bufferData( destino de enum , tamanho longo , uso de enum )

alvo - ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER

uso - STATIC_DRAW, STREAM_DRAW, DYNAMIC_DRAW

3

vazio bufferData(enum target , dados de objeto , uso de enum )

alvo e uso - o mesmo que parabufferData acima

4

vazio bufferSubData( destino enum , deslocamento longo , dados do objeto )

alvo - ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER

5 Objeto createBuffer()
6 vazio deleteBuffer( Buffer de objeto )
7

qualquer getBufferParameter(enum destino , enum pname )

alvo - ARRAY_BUFFER, ELEMENT_ ARRAY_BUFFER

pname - BUFFER_SIZE, BUFFER_USAGE

8 bool isBuffer( Buffer de objeto )