Resumo: Eu fico com a desaceleração do FPS assim que tento colorir os sprites (ou seja: multiplique a textura pela cor no shader do fragmento)
Detalhes:
Hardware: iPod touch 4
Estou desenhando 700 sprites na tela usando glDrawArrays. E sim, estou agrupando tudo isso em uma única chamada de empate. A seguir, mostra a estrutura de dados do Vertex:
struct Vertex {
float Position[2];
float Color[4];
float Texture[2];
};
Sim, estou enviando cores com cada vértice porque preciso seletivamente pintar alguns sprites, mas não outros. A seguir está o shader de fragmento que estou usando:
varying lowp vec2 TexCoord;
uniform sampler2D TextureSampler;
void main(void)
{
gl_FragColor = texture2D( TextureSampler, TexCoord );
}
Até agora está funcionando muito bem, me dando 60 FPS completos !!!
MAS
Assim que eu mudar o sombreador do fragmento para o seguinte (para permitir a coloração):
varying lowp vec4 DestinationColor;
varying lowp vec2 TexCoord;
uniform sampler2D TextureSampler;
void main(void)
{
gl_FragColor = texture2D( TextureSampler, TexCoord ) * DestinationColor;
}
Usando a seguinte textura png de 64x64, contendo canal alfa, renderizando com glEnable (GL_BLEND):
O desempenho cai para 47 FPS apenas devido a essa alteração única {apenas por multiplicação com UM vetor} (FPS medido usando instrumentos xcode e detetive OpenGL). Alguma idéia do que está acontecendo?
Obrigado.
Editar:
Eu também tentei retirar por atributo de cor do vértice:
struct Vertex {
float Position[2];
float Texture[2];
};
E modificando o sombreador de fragmento da seguinte maneira:
precision lowp float;
varying lowp vec2 TexCoord;
uniform sampler2D TextureSampler;
void main(void)
{
gl_FragColor = texture2D( TextureSampler, TexCoord ) * vec4(1.0,0.0,0.0,1.0);
}
Está rodando a 52 FPS para 700 sprites (um ganho de apenas 5 FPS). Portanto, isso não é interpolação, parece que a multiplicação é extremamente cara. Apenas esta multiplicação?
Respostas:
Eu não acho que o problema de desempenho esteja acontecendo na multiplicação, mas na interpolação do seu
DestinationColor
entre os triângulos, entre vértices e fragmentos de sombreamento. Você tem quatrofloat
segundos para interpolar entre os vértices das árvores, para cada fragmento para cada sprite.Para 700 sprites de 64x64 pixels cada, são 11468800 operações adicionais por quadro que você está solicitando à GPU para executar. É bem possível que você perca alguns vsyncs e, portanto, caia para 40-ish FPS.
Se você deseja que cada vértice tenha uma cor diferente, então você pode ter gradientes para cada sprite, não terá sorte. Existem outros truques que você pode querer experimentar, mas acho que não é esse o caso.
Como o que você parece estar fazendo é pintar cada sprite, você pode rebaixá-lo
DestinationColor
para auniform
, usá-lo diretamente no shader de fragmento e alterá-lo para cada chamada. Dessa forma, nenhuma interpolação ocorrerá. Você perderá todo o lote, mas poderá fazer um lote se os classificar por cor.fonte