Aprendendo WebGL Parte 4: drawArrays vs drawElements

Bem vindos ao meu primeiro tutorial sobre WebGL, buscarei transferir todo aprendizado que obtive nos últimos tempos lhe conduzindo do básico ao avançado.

Durante essa série de posts apresentarei códigos de exemplo que estarão disponíveis neste repositório do GitHUB.







Nessa parte do nosso tutorial vamos abordar algumas diferenças entre os 2 métodos de renderização do WebGL, drawArrays e drawElements.

Como vimos no post anterior, o momento em que chamamos um desses dois métodos é quando a mágica acontece, as shaders são executadas e a imagem da cena aparece no nosso canvas.

Se fossemos mudar nossa implementação anterior para exibir um cubo ao inves de um triângulo bastaria alterar os vértices:

Em seguida alterar a quantidade de itens renderizados:

Nada de mais não é mesmo?

Vamos agora ver uma nova opção de forma de renderização, ao invés de usarmos drawArrays, usaremos drawElements, mas como isso funciona?

Quando usamos o método drawArrays, cada attribute das shaders é carregado de forma sequencial nos buffers, no nosso caso o primeiro vec3 aVertexPosition é carregado com (-1.0, -1.0, 1.0) o segundo com (1.0, -1.0, 1.0) e assim sucessivamente na ordem em que eles aparecem no buffer.

Quando usamos o método drawElements nós precisaremos de um buffer auxiliar, um buffer de indíces que irá informar qual o indice do elemento será carregado na Shader, os vértices não serão mais renderizados na forma sequencial em que foram colocados no buffer, mas sim obedecendo o array de indíces.

Vejam no exemplo acima que a ordem que será renderizada é a ordem indicada no indexBuffer, então o primeiro vértice que será usado é o vértice do índice 1: vértice A, depois o vértice do índice 2: vértice B, depois o vértice do índice 1 novamente: vértice A, e assim sucessivamente.

Percebam que com isso conseguimos diminuir o tamanho do nosso vertexPositionBuffer porque os vértices repetidos podem ser reaproveitados, porém agora trabalhamos com 2 buffers distintos.

Como ficaria a nossa implementação se usássemos um indexBuffer?

Primeiramente precisamos ajustar os nossos vértices para reaproveitar os que são repetidos:

Depois criamos o nosso indexBuffer:

E por último mudamos a chamada para drawElements:

Prontinho, temos o mesmo resultado mas de uma forma diferente.

O código fonte completo dessas duas implementações estão disponíveis Neste Link

Mas na prática qual a diferença entre esses dois métodos?

Vantagens de usar drawElements
  • É possível economizar memória reciclando vértices repetidos
  • O processo de renderização fica teoricamente mais rápido devido a implementação do drawElements em diversas placas de vídeo (isso não acontece em 100% dos casos, existem diversas discussões sobre este assunto rolando pela internet)
Desvantagens de usar drawElements
  • Suporte limitado a mapas UV porque as vezes você quer carregar uma coordenada de uma face que está em um canto da imagem, mas a outra face que usa o mesmo vértice está em outro canto da imagem, logo são duas ou mais coordenadas UV possíveis para o mesmo vértice.
  • Suporte limitado a coloração de vértices. Aqui acontece o mesmo problema com os mapas UV.
  • Se torna praticamente inútil para renderizar partículas, já que nunca dois vértices estarão no mesmo ponto.
  • Aumento significativo da complexidade do algorítmo para processar animações de esqueleto (skeletal animations).

Em resumo, drawArray é por padrão sua melhor escolha em aplicações onde você irá carregar personagens ou cenas complexas, pense em usar drawElements quando quiser alguma otimização pesada ou quando estiver renderizando algo mais específico como experimentos gráficos ou efeitos exclusivos.

Por enquanto é isso pessoal, no próximo post continuaremos falando sobre formas de renderização e entenderemos a diferença entre usar gl.TRIANGLES, gl.POINTS, gl.LINES e etc.

Espero que façam bom proveito!
Share on Google Plus

Sobre Unknown

Sou um entusiasta de linguagens de programação e arquitetura de software. Vejo os projetos de software como partidas de xadrez onde as linguagens, os padrões e as técnicas devem ser usados com maestria para efetuar boas jogadas.
    Blogger Comment

0 comentários:

Postar um comentário