Comment charger les textures en OpenGL ES efficace
J'ai une connaissance de base de l'utilisation de OpenGL, surtout sur Android. Je suis de développer une application qui utilise OpenGL pour basculer entre le mode plein écran des images dans une voie rapide (car il est trop lent à l'aide de la normale Android-cadre).
Ce que j'ai trouvé, c'est que pour charger les textures, j'ai besoin de faire quelque chose comme:
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
vertexBuffer = byteBuffer.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
textureBuffer = byteBuffer.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
_gl = gl;
final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), _imageResourceId);
gl.glGenTextures(1, textures, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
Maintenant, étant donné que les images sont destinées à être en plein écran (et ils sont assez grand - 1024x1024), cela prend un certain temps, surtout depuis que j'ai besoin de charger 5 d'entre eux en même temps.
Donc j'ai besoin de vous poser quelques questions concernant les conseils de l'amélioration du code, en particulier à propos efficace de chargement (mais aussi en utilisant moins de mémoire si possible):
- si je décoder l'image bitmap de ne pas avoir de la transparence de pixels, à l'aide de la RGB_565 format, il va augmenter la vitesse de chargement des images pour OpenGL (ou de la phase de décodage)?
- l'entrée bitmap avoir une largeur et une hauteur qui sont des puissances de 2 ou je peux le laisser OpenGL ne prendre que la partie qu'il veut, qui aura cette règle? Je veux dire, je peux peut-être faire la
texImage2D
commande de ne prendre qu'une partie de l'image bitmap? - je peux peut-être même de décoder seulement cette partie depuis le début (donc, si j'ai une énorme image de 10000x10000, je peux décoder seulement un 1024x1024 partie de, et de le donner à OpenGL)?
- est-il possible de charger et d'afficher seulement la première image, et à l'arrière-plan de charge du reste? J'ai entendu dire que vous ne pouvez pas envoyer les images à OpenGL dans un thread qui n'est pas celui qui le manipule. Est-il judicieux de les charger sur le
onDrawFrame
méthode de laGlRenderer
, disons, la deuxième fois qu'il me demande? - Je me souviens que j'ai entendu parler d'une astuce à propos de la fusion de plusieurs images en une seule image (l'un après l'autre, de gauche à droite), de sorte qu'elle peut avoir une certaine augmentation de la vitesse de la phase de décodage. Pas sûr quel est le nom de cette technique. Est-il encore possible pour OpenGL ES sur Android?
- est-il possible d'éviter de créer une occurrence de Bitmap et de laisser le décodage fait dans une plus moyen natif (NDK , peut-être)? Selon mes tests, le décodage d'un fichier PNG de taille 1024 x 1024 sur un émulateur prend environ 400ms-700ms, encore de l'envoyer à OpenGL prend environ 50ms-70ms.
- à l'aide de Procrank, j'ai découvert que l'OpenGL peut prendre beaucoup de mémoire. Est-il possible d'utiliser moins de mémoire? Peut-être mieux utiliser les textures types?
- depuis Android peut fonctionner sur plusieurs types d'appareils, est-il possible de mettre dans le manifeste d'une exigence de combien de mémoire est nécessaire pour l'application à exécuter, de sorte que les gens avec trop peu de mémoire ne sera pas en mesure de l'installer?
@Majid Max :
- donc c'est suffisant pour décoder cette façon, et de l'envoyer à OpenGL, ou devrais-je également définir quelque chose de spécial lors de l'envoi d'openGL?
- il n'existe pas une commande pour prendre partielle d'une partie de l'image bitmap?
- Je voulais dire, je peux décoder seulement une partie de la partie du fichier qui doit être stockée dans un bitmap, au lieu de l'ensemble de l'image bitmap?
- donc, la seule chose que je peux faire c'est de charger tout au début, et ensuite l'utiliser? Comment pourrait-il être? Comment faire des jeux de le manipuler? Je veux dire, ils montrent une étape après l'autre, même avec quelque chose qui ressemble à un OpenGL généré barre de progression. Ceci est très problématique.
- ce que je vais décrire est disponible sur le web. Par exemple, au lieu de chargement multitude de minuscules images, la page web contenant une seule image et des cartes de quelle partie de celui-ci devrait être indiqués, le cas. Un autre nom car il est les sprites. Exemple ici .
- Je vois. Je suppose que je doit appeler glDeleteTextures quand je vois il n'y a pas plus utilisé, non?
- comment dois-je faire? Que dois-je changer dans le code?
- ce qui se passe lorsque j'utilise beaucoup de mémoire? Est-il une chose telle que la RAM virtuelle (utilise la mémoire de stockage interne peut-être) quand il n'y a pas de libérer de la mémoire vive? J'en ai entendu parler sur Google IO vidéo, mais il semble qu'ils n'étaient pas sûrs de la réponse. Lien ici. Ils ont seulement dit s'attendre à plus de plantages quand une telle chose se produit.
@Majid Max :
1+2+3. ?
- cela pourrait fonctionner. Tu veux dire que je fais un nouveau thread qui va charger les images, puis d'envoyer les résultats à l'OpenGL thread qui va lier les textures de l'image bitmap? Je pourrais peut-être utiliser une approche similaire pour asyncTask, et l'utilisation publishprogress.
- c'est aussi une bonne chose. Avez-vous un lien que je devrais lire à ce sujet? Ou peut-être un fragment de code à modifier dans mon code?
- grâce.
- donc je pense que c'est la chose la plus facile à utiliser ETC1. Cependant, il ne prend pas en charge la transparence à tous, alors, selon ce lien, j'ai besoin d'utiliser une autre texture pour ça, mais je ne peux pas trouver un exemple pour cela.
- ce que je peux prendre de la mémoire disponible que je peux utiliser? Puis-je supposer, par exemple, que tous les appareils Android peut m'offrir de 200 mo de mémoire vidéo que je peux utiliser pour l'OpenGL?
OriginalL'auteur android developer | 2012-09-03
Vous devez vous connecter pour publier un commentaire.
oui, si vous n'avez pas besoin de la transparence (alpha) utiliser un format sans alpha, et les petits formats comme (RGB565) signifie une plus petite taille des textures qui certainement d'accélérer le décodage et de chargement pour opengl.
certainement OUI, si vous chargez une texture non puissance de 2, largeur/hauteur, opengl va allouer une texture avec la puissance de 2 (513/513 texture deviendra 1024/1024), et qui signifie que vous perdez de la vram de la mémoire. et vous ne pouvez pas commande opengl pour prendre une partie de l'image, parce que "teximage2d" prend la largeur/hauteur de l'image chargée, et en précisant toutes les autres valeurs peuvent vous donner une image endommagée (si pas de concassage de l'application).
pas de commentaire.
Je ne suis pas sûr de cela, il y a déjà un multi-fileté moteur de rendu basé sur opengl. et vous pouvez charger une texture (de l'autre thread), tandis que l'émission d'un rendu de commande (au moins en natif C/C++, vous ne savez pas à propos de java). et NON, ne jamais essayer de charger une texture dans la boucle de rendu, c'est une mauvaise pratique.
pas sûr de ce que vous voulez dire ici
c'est le meilleur moyen, le code natif C/C++) toujours mieux
(si vous voulez dire de mémoire vidéo ici) oui, en utilisant un format de compression de texture comme ETC1, PVRTC, ATC toujours une bonne idée, il prendre moins de mémoire vidéo mémoire, et produit une meilleure performance.
envisager de passer à une solution de secours (même les plus petites textures) plutôt que l'abattage hors bas-de-gamme d'appareils.
EDIT:
4.. vous commencer le chargement du contenu (images) dans un thread séparé qui indiquent le thread de rendu le pourcentage du processus de chargement, ce qui peut être utilisé pour dessiner une barre de progression pendant le processus de chargement.
5.. ce truc appelé "texture atlas" et c'est pour accélérer le rendu pas le chargement.
6.. après le chargement d'une image décodée dans une texture opengl, vous êtes libre de supprimer l'image décodée (à partir de la mémoire système) que vous chargez la suivante. et après tu fait à l'aide de la texture opengl, vous pouvez le supprimer (de mémoire vidéo).
7.. la compression de texture est spécifique à un matériel donné extensions d'opengl, donc vous devez vérifier si la compression de texture extension est présente et à utiliser avec "glCompressedTexImage2D fonction" au lieu de "texImage2D".
PVRTC pour les GPU PowerVR;
ATC pour AMD GPU;
CFSA pour le Mali GPU;
ETC1 un standard de format de texture (pris en charge dans android 2.2+).
8. lorsque vous avez terminé le chargement d'une image de texture opengl, l'image n'est plus nécessaire. donc, vous devez libérer la mémoire ram inutile de contenu (images).
EDIT2:
5.. http://http.download.nvidia.com/developer/NVTextureSuite/Atlas_Tools/Texture_Atlas_Whitepaper.pdf
7.. après avoir chargé deux textures ETC (ex: la première texture maintenez la couleur, et le deuxième magasin de l'alpha dans le canal rouge) à l'aide de "glCompressedTexImage2D" en opengl (disons textureId1, textureId2), lier les deux textures dans deux unités de texture :
et puis créer un shader programme avec le fragment shader:
enfin, lier les deux shader texture des échantillonneurs pour les deux textures des unités (qui pointent vers les deux textures ETC):
8.. vous ne pouvez pas assumer toute chose, vous gardez l'allocation de textures et de tampon (si nécessaire) jusqu'à obtenir GL_OUT_OF_MEMORY, que vous aurez à dégager d'autres ressources non utilisées (textures, tampons, ...).
j'ai mis à jour ma réponse, j'espère que cette aide.
CFSA n'est pas disponible sur rien pour le moment. Pour le Mali, les systèmes basés je pense que vous devez utiliser ETC, qui est également exposé sur certains autres systèmes (selon le vendeur)
OriginalL'auteur Majid Max
Si vous êtes toujours à la recherche d'un exemple pour le rendu des images bitmap à un InputSurface en utilisant OpenGL.
J'ai été en mesure d'obtenir ce travail.
Regardez mes réponses ici.
OriginalL'auteur David Knight
Je pense que vous devriez vérifier http://www.andengine.org/ Il vous permettra d'économiser beaucoup de temps et de travail...
OriginalL'auteur Verthosa