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