Tengo un conocimiento básico sobre el uso de OpenGL, especialmente en Android. Estoy desarrollando una aplicación que utiliza OpenGL para cambiar entre imágenes de pantalla completa de una manera rápida (ya que es demasiado lento con el marco Android normal).Cómo cargar texturas en OpenGL ES de manera eficiente
Lo que he encontrado es que con el fin de cargar texturas, necesito hacer algo como:
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();
Ahora, ya que las imágenes están destinados a ser pantalla completa (y son bastante grandes - 1024x1024), esto lleva tiempo, especialmente porque necesito cargar 5 de ellos al mismo tiempo.
por eso es necesario hacer algunas preguntas acerca de consejos para mejorar el código, sobre todo acerca de la carga eficiente (pero también utilizando menos memoria si es posible):
si decodificar el mapa de bits para no tener píxeles de transparencia, utilizando el formato RGB_565, ¿aumentará la velocidad de carga de las imágenes a OpenGL (o la fase de decodificación)?
¿el mapa de bits de entrada tiene que tener un ancho y alto que sean potencias de 2 o puedo dejar que OpenGL tome solo la parte que quiere, que tendrá esta regla? Quiero decir, ¿quizás puedo hacer que el comando
texImage2D
tome solo una parte del mapa de bits?tal vez incluso puedo decodificar solo esta parte desde el principio (entonces, si tengo una imagen enorme de 10000x10000, puedo decodificar solo una parte de 1024x1024 y dársela a OpenGL)?
es posible cargar y mostrar sólo la primera imagen, y en el fondo cargar el resto? Escuché que no puedes enviar bitmaps a OpenGL en un hilo que no es el que maneja. ¿Tiene sentido cargarlos en el método del
GlRenderer
, por ejemplo, la segunda vez que se llama?Recuerdo que escuché un consejo sobre cómo fusionar varias imágenes en una sola imagen (una después de otra, de izquierda a derecha), para que tenga un impulso de velocidad para la fase de decodificación. No estoy seguro de cuál es el nombre de esta técnica. ¿Todavía es posible para OpenGL ES en Android?
es posible evitar la creación de una instancia de Bitmap y dejar que el hecho de decodificación de una manera más natural (NDK, tal vez)? De acuerdo con mis pruebas, decodificar un archivo PNG de tamaño 1024x1024 en un emulador toma alrededor de 400ms-700ms, sin embargo, enviarlo a OpenGL toma alrededor de 50ms-70ms.
usando Procrank, he descubierto que OpenGL puede tomar una gran cantidad de memoria. ¿Es posible hacer que use menos memoria? Tal vez usar mejores tipos de texturas?
Dado que Android puede funcionar en muchos tipos de dispositivos, ¿es posible poner en el manifiesto un requisito de cuánta memoria se necesita para ejecutar la aplicación, para que las personas con muy poca memoria no puedan ¿instalarlo?
@Majid Max:
por lo que es suficiente para decodificar esta forma y enviarla a OpenGL, o debería también establecer algo especial al enviar a OpenGL?
no existe tal comando para tomar una parte parcial del mapa de bits?
Quiero decir, ¿puedo decodificar solo una parte parcial del archivo que se almacenará en un mapa de bits, en lugar de todo el mapa de bits?
así que lo único que puedo hacer es cargar todo al principio, y luego usarlo todo? ¿Como puede ser? ¿Cómo lo manejan los juegos? Quiero decir, muestran una etapa tras otra, incluso con algo que se parece a una barra de progreso generada por OpenGL. Esto es muy problemático
lo que estoy describiendo está disponible en la web también. Por ejemplo, en lugar de cargar varias imágenes diminutas, la página web contiene una sola imagen y mapea qué parte de ella se debe mostrar en dónde. Otro nombre para esto es sprites. Ejemplo here.
Ya veo. Supongo que también debería llamar a glDeleteTextures cuando vea que ya no se utilizan, ¿verdad?
¿cómo hago eso? ¿Qué debería cambiar en el código?
¿Qué sucede cuando uso mucha memoria? ¿Hay algo así como RAM virtual (quizás use almacenamiento interno) cuando no hay RAM libre? He oído sobre esto en el video de Google IO, pero parece que tampoco estaban seguros de la respuesta. Enlace here. Solo dijeron esperar más bloqueos cuando ocurra algo así.
@Majid Max:
1 + 2 + 3. ?
esto podría funcionar. ¿Quiere decir que hago un nuevo hilo que cargará los mapas de bits, y luego enviaré los resultados al hilo de OpenGL que unirá las texturas al mapa de bits? Tal vez podría utilizar un enfoque similar a asyncTask y usar publishprogress.
eso también es una buena cosa. ¿Tienes algún enlace que deba leer al respecto? O tal vez un fragmento para cambiar en mi código?
gracias.
así que creo que es lo más fácil de usar ETC1. Sin embargo, no admite transparencia en absoluto, por lo que de acuerdo con this link, necesito usar otra textura solo para eso, pero no puedo encontrar una muestra para esto.
¿Qué puedo suponer sobre la memoria disponible que puedo usar? ¿Puedo asumir, por ejemplo, que todos los dispositivos Android me pueden ofrecer 200 MB de memoria de video que puedo usar para OpenGL?
lamentablemente no puedo usarlo ya que necesito trabajar con API de Android y OpenGL. Sé de esta solución (y libGDX). simplemente no puedo usarlos, especialmente porque necesito poner las vistas en un viewPager. –