Bem vindo ao tutorial número 5 nessa série de tutoriais WebGL. Ao invés de um triângulo e um quadrado, vamos agora criar uma pirâmide e um cubo. O tutorial é baseado na lição 5 do LearningWebGL.
Veja o resultado obtido:
Um aviso (de novo): estas lições estão baseadas no conteúdo dado na disciplina de Introdução à Computação Gráfica do Instituto de Matemática e Estatística da USP. Mesmo assim, outras pessoas que não sejam alunos dessa disciplina podem aproveitar e compreender o conteúdo destes tutoriais. Se você não fez o tutorial 2, o tutorial 3 e o tutorial 4, recomendo fazê-lo antes de avançar para este tutorial. Se você se sente seguro em compreender o que se passa aqui, pode continuar. Se houver falhas ou achar que falta alguma coisa para melhorar o tutorial, não hesite em me avisar.
As diferenças entre o código desta lição e da anterior se concentram
exclusivamente nas funções animar
,
iniciarBuffers
, e desenharCena
. Antes
disso, uma pequena mudança: ao invés de rTri e rQuad, vamos
renomeá-las para rPiramide
e rCubo
(na
declaração e nos usos pelas funções).
Tarefa: Renomeie as variáveis (a localização está indicada nos comentários).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Uma pirâmide e um cubo contém mais vértices do que um triângulo e um quadrado. O código para enviar o triângulo ou a pirâmide é o mesmo (só adicionando mais vértices, posições e cores).
Vamos renomear tudo que tenha a palavra triangle para colocar piramide (para fazer mais sentido ao tutorial).
Tarefa: Mude na função desenharCena
os
nomes triangleVertexPositionBuffer
e
triangleVertexColorBuffer
para
piramideVertexPositionBuffer
e
piramideVertexColorBuffer
.
318 319 320 321 322 323 324 325 |
|
Tarefa: Mude também para o cubo
334 335 336 337 338 |
|
Tarefa: Renomeie também na declaração das variáveis
39 40 41 42 |
|
Agora vamos mostrar algo diferente para desenhar o cubo. Há 3 estratégias para desenhá-lo:
- Usar um "fita" de triângulos (TRIANGLE_STRIP), no qual após os três pontos de um triângulo, você define apenas mais um ponto e ele forma um outro triângulo aproveitando os dois últimos pontos do triângulo anterior, fazendo esse processo repetidamente. O problema é que queremos faces de cores diferentes do cubo, e três faces compartilham um mesmo ponto no cubo, mas não é possível determinar 3 cores para o mesmo vértice.
-
Desenhar as 6 faces separadamente (4 vértices cada, totalizando 24
posições e 24 cores), mas aí precisaríamos chamar o
drawArrays
6 vezes. Imagina todo um ambiente virtual sendo desenhado dessa forma, multiplicando as chamadasdrawArrays
. É bastante custoso computacionalmente. Preferimos ter o mínimo de chamadas de desenho. - Enviar os 8 vértices do cubo + 4 cores, e referenciá-los usando índices nos triângulos. Então os 12 triângulos do cubo (2 para cada face) fariam referência a 3 vértices e uma cor. Separando os dados dos vértices com suas referências (triângulos) faz com que você possa reusar os vértices para outros triângulos, economizando dados enviados à GPU. Obviamente você precisa adicionar as referências, mas elas são números inteiros, de poucos bytes. Vou apresentar esse modo para esclarecer um pouco (talvez seja necessário mais um ou dois tutoriais para compreender a real vantagem disso, não se preocupe).
Não vamos mais usar o drawArrays
, e sim
drawElements
. É que o primeiro trabalha diretamente com
os vértices, e o segundo trabalha com índices, referências aos
vértices. Então precisamos:
- Criar o buffer para os índices desses vértices;
- Usá-los no momento do desenho.
Para usá-los, simplesmente execute o bindBuffer
nesse
buffer dos índices (para o cubo, vamos chamar de
cuboVertexIndexBuffer
).
Tarefa: Renomeie também na declaração das variáveis
338 339 340 341 |
|
O tipo do buffer para os índices é o
ELEMENT_ARRAY_BUFFER
ao invés de
ARRAY_BUFFER
.
A função drawElements
precisa do tipo de polígono a ser
desenhado, o número de polígonos (você não é obrigado a desenhar
todos os triângulos naquele momento), o tipo de dado (os índices
geralmente são guardados como inteiros não-negativos de 1 byte -
UNSIGNED_BYTE - ou 2 bytes - UNSIGNED_SHORT) e a
referência para o buffer (com o bindBuffer, não precisamos dessa
opção).
Tarefa: Adicione a declaração da variável para o buffer de índices do cubo.
39 40 41 42 43 44 |
|
Vamos atualizar os buffers lá na função iniciarBuffers
.
Tarefa: Renomeie as variáveis e edite os vértices e
índices dos buffers na função iniciarBuffers
(buffer de
posição)
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
|
Tarefa: Renomeie as variáveis e edite os vértices e
índices dos buffers na função iniciarBuffers
(buffer de
cores)
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
|
Tarefa: Agora para o cubo => Renomeie as
variáveis e edite os vértices e índices dos buffers na função
iniciarBuffers
(buffer de posições)
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
|
No OpenGL (e WebGL) se dois vértices tiverem qualquer um dos atributos diferentes entre si (posição ou cor ou coordenada de textura ou ...), mesmo que todos os outros sejam idênticos, então eles são diferentes vértices. Nesse exemplo, os dados que se repetem são as cores (4 vezes). Então vamos criar as cores distintas e replicá-los.
Tarefa: Renomeie as variáveis e edite os vértices e
índices dos buffers na função iniciarBuffers
(buffer de
cores)
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 |
|
E agora vamos criar os nossos índices para desenhar nosso cubo. Se um triângulo precisar dos vértices que estão na segunda, quarta e quinta posições do buffer (de posição ou de cor), então precisamos inserir os valores 1, 3 e 4 (o primeiro está no índice 0).
Tarefa: Adicione esse código abaixo do último
código supracitado na função iniciarBuffers
.
284 285 286 287 288 289 290 291 292 293 294 295 296 |
|
Lembra do UNSIGNED_SHORT? Ele usa 2 bytes (16 bits), por isso estamos usando Uint16Array.
Exercícios:
-
Cor do Cubo
- Se o cubo for de apenas uma cor, a variável
vertices
só precisa de 8 vértices ecores
de 1 cor (o número de índices é o mesmo usandogl.TRIANGLES
). Tente fazer isso. - Tipo de Primitivas de Desenhos
- Se o cubo for de apenas uma cor, a variável
-
Crie Novas Formas Geométricas
- Deve-se Alterar o Modelo para que o Cubo Orbite o Triangulo, sendo que os dois não devem sair da Tela.
- Baseado no último dígito do número de matrícula, desenha uma das figuras abaixo e posicione rotacionando sobre o Eixo X,Y com Shier Aplicado de 20Graus no Plano X.
- Os .JS serão usados as mesmas versões do Tutorial