Blog do Eduardo Costa Meu blog pessoal

30Abr/110

Otimização de cubos

Cá estou eu trabalhando em um pequeno teste envolvendo cubos e OpenGL ES. Gerei alguns números impressionantes e gostaria de compartilhar.

Bem, quem manja de OpenGL sabe que glVertex com GL_TRIANGLES é o pior jeito de gerar objetos 3D (embora seja o mais simples). Usar Vertex Buffer Objects, glDrawElements e GL_TRIANGLE_STRIP é algo bem melhor. Entretanto, faria muito noob se borrar nas calças e dizer que Direct3D é melhor se as pessoas aprendessem primeiro pelo jeito mais otimizado.

Vamos aos números. Em um cubo, temos 6 faces, correto? Cada face é representável com dois triângulos e cada um com três vértices. Dá um total de 36 (6x3x2) pontos ou "chamadas ao glVertex". Para definir cada ponto, temos 3 posições (X, Y, Z), mais uma coordenada constante extra para shaders (W) , mais duas coordenadas de textura (U, V). Se todas forem "float", são 6 dados de 4 bytes, ou seja, 24 bytes por ponto. No total, o cubo tem 864 bytes (36x24).

Como melhorar isso? Em primeiro lugar, usando shorts no lugar de floats para XYZW. Cada ponto fica com 16 bytes (4 shorts de 2 bytes mais 2 floats de 4 bytes). Já reduzimos o tamanho do cubo para 574 bytes (36x24). Melhorou, mas não está bom.

Usando triangle strips, reduzimos a quantidade de vértices. Em virtude das texturas que estou aplicando (uma em cima, uma para os lados e uma para baixo), posso fazer um "strip" para os lados, "casar" com a parte de cima e "pular" para a parte de baixo. Não sei descrever melhor, mas isso me permite descrever o cubo com apenas 22 pontos. Reduz para 352 bytes (16x22). Calma que ainda vem mais!

Com VBOs, ainda mantendo o padrão das texturas, descobre-se que esses 22 pontos tem muito "repeteco", gerando apenas 15 pontos únicos. Isso são 240 bytes (16x15), mas falta o buffer de índices. Criando esse IBO, temos os 22 pontos representados como minúsculos shorts. São mais 44 bytes (22x2). No total, temos 284 bytes (44+240)!

Ou seja, nesse caminho todo, o computador precisava movimentar e processar 864 bytes (quase 1k) por cubo. Otimizando, caiu para 284! Isso representa uma economia de quase 68%! E, nesse caso, também representa uma otimização de processamento, VBOs reduzem as cópias entre memória de CPU e memória de GPU.

A parte legal é que fica tudo intuitivo depois que você entende o porquê.