sábado, 2 de fevereiro de 2013

Batching Sprite


Batching Sprite

Se nós tentamos usarmos o debugTexture do tutorial texturas para processar todos os nossos sprites e tiles, as chances de que haja problemas de desempenho são grandes. Isto é porque estamos apenas colocando um sprite em um momento para a GPU. O que nós precisamos é de "lote" sprites para a melhoria do desempenho, por isso usamos um SpriteBatch.

Intro

Como discutido no tutorial texturas, um sprite é nada mais do que um conjunto de vértices que compõem uma forma retangular. Cada vértice contém um certo número de atributos que a definem, tais como:

Posição (x, y) - onde o vértice encontra-se na tela
TexCoord (s, t) - o que a região da nossa textura deseja processar
Cor (r, g, b, a) - o vértice de cor, utilizado para especificar tingimento ou transparência
Doseadores mais sprites são bastante simples de usar, e pode ser parecido com isso no seu jogo:

//called on game creation
public void create() {
    //create a single batcher we will use throughout our application
    spriteBatch = new SpriteBatch();
}

//called on frame render
public void render() {
    //prepare the batch for rendering
    spriteBatch.begin(); 

    //draw all of our sprites
    spriteBatch.draw(mySprite1, x, y);
    spriteBatch.draw(mySprite2, x, y);
    ...

    //end the batch, flushing the data to GPU
    spriteBatch.end();
}

//called when the display is resized
public void resize(int width, int height) {
    //notify the sprite batcher whenever the screen changes 
    spriteBatch.resize(width, height);
}
Primeiro, begin() o batch, nós simplesmente dizemos que ele está em "modo de desenho" e chamamos o use() em nosso programa de shader. Então, chamando spriteBatch.Draw (...) colocamos as informações da vértice do sprite (posição, texcoord, cor) em uma pilha muito grande. Os vértices não são passados ​​para a GPU até que uma das seguintes situações ocorra:

O batch é forçado a render com o end () ou em outra ligação que libera o batch, como flush ()

O usuário tenta desenhar um sprite que usa uma textura diferente do que o último. O batch tem de ser limpado e novamente  texturizar antes de podermos continuar

Chegamos a capacidade de nossa pilha, por isso precisamos liberar para começar tudo de novo

Esta é a ideia básica por trás de um doseador sprite. Como você pode ver, usando muitas texturas vai levar a muitas chamadas (como o batch terá de lavar para cada nova textura). É por isso que uma textura atlas (folha de sprite AKA) é sempre recomendado, que nos permite prestar muitos sprites em uma chamada de desenho único.


A API LWJGL-básico inclui uma implementação SpriteBatch mínima para se usar


TextureRegion

Como discutido, para o melhor desempenho, deve-se usar um atlas de texturas e desenhar as regiões dele (AKA sub-imagens) para colocar as sprites em nosso jogo. Para isso temos uma classe TextureRegion. Ela nos permite especificar em pixels a posição do eixo (x, y) e seu tamanho (altura, largura) da nossa imagem 

Vamos dar um exemplo, onde queremos tornar nossa Sprite um destaque:





Imagem da Sprite








Podemos ter uma TextureRegion da Sprite com o seguinte:
//specify x, y, width, height of tile
region = new TextureRegion(64, 64, 64, 64);
Como você pode ver, o  TextureRegion nos permite obter sub-imagens sem se preocupar com o cálculo das coordenadas da textura. Podemos, então, desenhar nossa sprite do Batshing Sprite  assim:
... inside SpriteBatch begin / end ...
spriteBatch.draw(region, x, y);

Vertex Color

Nós podemos mudar a coloração e transparência de todos os sprites através da "cor de vértice."

O RGB resultante é multiplicada pela cor, textura, assim se utilizou uma textura branca (1, 1, 1, 1) e uma cor especificada na vértice como (1, 0, 0, 1), o resultado seria o vermelho. O componente alfa da cor nos permite ajustar a opacidade dos sprites desenhados na tela.

spriteBatch.begin();

//draw calls will now use 50% opacity
spriteBatch.setColor(1f, 1f, 1f, 0.5f);
spriteBatch.draw(...);
spriteBatch.draw(...);

//draw calls will now use 100% opacity (default)
spriteBatch.setColor(1f, 1f, 1f, 1f);
spriteBatch.draw(...);

spriteBatch.end();
Na série anterior, pensávamos que nossa texturas era um quadrado por ter quatro pontas, mas na realidade o Sprite Batch vai usar dois triângulos adjacentes para representar um sprite retangular. Os vértices podem ser ordenados de maneira diferente dependendo do motor (No LibGDX tende-se a usar da parte inferior para a esquerdo), mas a ideia básica é assim:














Um única sprite  possui dois triângulos ou seis vértices. Cada vértice tem oito atributos (X, Y, S, T, R, G, B, A), que juntos formam Posição, TexCoord e Cor. Isto significa que a cada sprite, estamos empurrando 48 floats para uma pilha! Um Sprite Batcher mais otimizado pode compactar o RGBA em um único float , ou pode abrir mão de algumas cores da vértice.

E agora?


Criar o seu próprio batcher Sprite não é fácil, e requer a compreensão de shaders, buffers de vértice, e matemática matriz básica. Antes de mergulhar nestes tópicos avançados,  recomendo ficar mais expete com o SpriteBatcher fornecido para você pelo LWJGL-básico. Alternativamente, você pode usar o LibGDX como a implementação, pois ele é muito semelhante. Você também deve se sentir confortável com GLSL antes de tentar a sua própria batcher Sprite.

Se você ainda está interessado em aprender mais sobre como tudo funciona, veja o ShaderProgram e os artigos SpriteBatcher.

Fonte: https://github.com/mattdesl/lwjgl-basics/wiki/Sprite-Batching

0 comentários:

 
;