Résumé: je reçois un ralentissement FPS dès que j'essaie de teinter les sprites (c'est-à-dire: multiplier la texture avec la couleur dans le fragment shader)
Détails:
Matériel: iPod touch 4
Je dessine 700 sprites sur l'écran à l'aide de glDrawArrays. Et oui, je regroupe tout cela en un seul appel. Voici la structure des données Vertex:
struct Vertex {
float Position[2];
float Color[4];
float Texture[2];
};
Oui, j'envoie de la couleur avec chaque sommet car j'ai besoin de teinter sélectivement certains sprites mais pas d'autres. Voici le fragment shader que j'utilise:
varying lowp vec2 TexCoord;
uniform sampler2D TextureSampler;
void main(void)
{
gl_FragColor = texture2D( TextureSampler, TexCoord );
}
Jusqu'à présent, il fonctionne très bien, me donnant 60 FPS complets !!!
MAIS
Dès que je change le shader du fragment comme suit (pour autoriser la teinture):
varying lowp vec4 DestinationColor;
varying lowp vec2 TexCoord;
uniform sampler2D TextureSampler;
void main(void)
{
gl_FragColor = texture2D( TextureSampler, TexCoord ) * DestinationColor;
}
Utilisation de la texture png 64x64 suivante contenant le canal alpha, rendu avec glEnable (GL_BLEND):
Les performances chutent à 47 FPS uniquement en raison de ce changement unique {simplement par multiplication avec UN vecteur} (FPS mesuré à l'aide d'instruments xcode et d'un détective OpenGL). Une idée sur ce qu'il se passe ?
Merci.
Éditer:
J'ai également essayé de supprimer l'attribut de couleur par sommet:
struct Vertex {
float Position[2];
float Texture[2];
};
Et en modifiant le fragment shader comme suit:
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);
}
Il tourne à 52 FPS pour 700 sprites (un gain de seulement 5 FPS). Ce n'est donc pas de l'interpolation, il semble que la multiplication soit extrêmement coûteuse. Juste UNE SEULE multiplication?
Réponses:
Je ne pense pas que le problème de performance se produit sur la multiplication, mais sur l' interpolation de votre à
DestinationColor
travers les triangles, entre les vertex et les shaders de fragments. Vous avez quatrefloat
s pour interpoler entre les sommets des arbres, pour chaque fragment pour chaque sprite.Pour 700 sprites 64x64 pixels chacun, cela représente 11468800 opérations supplémentaires par image que vous demandez au GPU d'effectuer. Il est tout à fait possible que vous manquiez des vsyncs et que vous tombiez donc à 40 FPS.
Si vous voulez que chaque sommet ait une couleur différente, afin que vous puissiez avoir des dégradés pour chaque image-objet, vous n'avez pas de chance. Il y a aussi d'autres astuces que vous voudrez peut-être essayer, mais je pense que ce n'est pas le cas.
Étant donné que ce que vous semblez faire est de teinter chaque image-objet, vous pouvez rétrograder votre
DestinationColor
à ununiform
, l'utiliser directement dans le fragment shader et le changer pour chaque appel. De cette façon, aucune interpolation n'aura lieu. Vous perdrez l'intégralité du traitement par lots, mais vous pourrez peut-être un traitement par lots si vous les triez par couleur.la source