2012-09-03 32 views
5

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):

  1. 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)?

  2. ¿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?

  3. 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)?

  4. 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?

  5. 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?

  6. 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.

  7. 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?

  8. 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:

  1. 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?

  2. no existe tal comando para tomar una parte parcial del mapa de bits?

  3. 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?

  4. 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

  5. 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.

  6. Ya veo. Supongo que también debería llamar a glDeleteTextures cuando vea que ya no se utilizan, ¿verdad?

  7. ¿cómo hago eso? ¿Qué debería cambiar en el código?

  8. ¿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. ?

  1. 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.

  2. 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?

  3. gracias.

  4. 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.

  5. ¿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?

Respuesta

-1

creo que debe salir http://www.andengine.org/ Se le ahorrará una gran cantidad de tiempo y trabajo ...

+0

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. –

5
  1. sí, si usted no necesita la transparencia (alfa) utilizan un formato sin alfa, y formatos más pequeños como (RGB565) significa texturas de menor tamaño que sin duda aceleran la decodificación y la carga a opengl.

  2. definitivamente SÍ, si carga una textura sin potencia de 2 de ancho/alto, opengl asignará una textura con la siguiente potencia de 2 (la textura 513/513 se convertirá en 1024/1024), y eso significa que usted está desperdiciando memoria vram. y no se puede ordenar que OpenGL tome una parte de la imagen porque "teximage2d" toma ancho/alto de la imagen cargada, y especificar cualquier otro valor le dará una imagen dañada (si no está triturando la aplicación).

  3. sin comentarios.

  4. No estoy seguro de eso, ya existe un motor de representación de subprocesos múltiples basado en opengl. y puede cargar una textura (desde otro hilo) mientras emite un comando de renderizado (al menos en C/C++ nativo, no estoy seguro acerca de java). y NO, nunca intentes cargar una textura en el bucle de renderizado, es una mala práctica.

  5. no está seguro de lo que quiere decir aquí

  6. esta es la mejor manera, el código nativo (C/C++) siempre mejor

  7. (si se refiere a VRAM aquí) sí, utilizando una compresión de texturas formato como ETC1, PVRTC, ATC siempre es una buena idea, toma menos memoria vram y produce un mejor rendimiento.

  8. considere cambiar a una solución alternativa (incluso texturas más pequeñas) en lugar de cortar los dispositivos de gama baja.

EDIT:

4 .. empezar a cargar los contenidos (imágenes) en un hilo separado que indican a la prestación enhebrar el porcentaje de proceso de carga, esto puede ser usado para dibujar una barra de progreso para el proceso de carga

5 .. este truco llamado "atlas de texturas" y es para acelerar el renderizado no la carga.

6 .. después de cargar una imagen decodificada en una textura opengl, puede borrar la imagen decodificada (desde la memoria del sistema) después de cargar la siguiente. y una vez que haya terminado de usar la textura OpenGL, puede eliminarla (de la memoria de video).

7 .. La compresión de textura es extensiones OpenGL específicas del hardware, por lo que debe comprobar si la extensión de compresión de textura está presente y luego usarla con la función "glCompressedTexImage2D" en lugar de "texImage2D". PVRTC para PowerVR GPU; ATC para AMD GPU; ASTC para la GPU de Malí; ETC1 un formato de textura estándar (compatible con Android 2.2+).

8 .. Cuando haya terminado de cargar una imagen para abrir la textura, la imagen ya no es necesaria. por lo tanto, debe liberar el ariete de contenidos innecesarios (imágenes).

Edit2:

5 .. http://http.download.nvidia.com/developer/NVTextureSuite/Atlas_Tools/Texture_Atlas_Whitepaper.pdf

7 ..después de haber cargado dos texturas ETC (por ejemplo: la primera textura contiene el color y la segunda tienda alfa en el canal rojo) usando "glCompressedTexImage2D" en opengl (digamos textura1d1, texturaD2), une las dos texturas en dos unidades de textura:

glActiveTexture(GL_TEXTURE0); 
glBindTexture(GL_TEXTURE_2D, textureId1); 

glActiveTexture(GL_TEXTURE1); 
glBindTexture(GL_TEXTURE_2D, textureId2); 

y luego crear un programa de sombreado con la siguiente shader fragmento:

uniform sampler2D  sTexture1; 
uniform sampler2D  sTexture2; 
varying mediump vec2 vTexCoord; 

void main() 
{ 
    gl_FragColor.rgb = texture2D(sTexture1, vTexCoord).rgb; 
    gl_FragColor.a = texture2D(sTexture2, vTexCoord).r; 
} 

finalmente, se unen los dos muestreadores shader de textura para las dos unidades de texturas (que apuntan a los dos ETC texturas):

GLint texture1Sampler = glGetUniformLocation(programObject, "sTexture1"); 
GLint texture2Sampler = glGetUniformLocation(programObject, "sTexture2"); 

glUniform1i(texture1Sampler, GL_TEXTURE0); 
glUniform1i(texture2Sampler, GL_TEXTURE1); 

8 ... no puede asumir nada, sigue asignando texturas y búfer (según sea necesario) hasta que obtenga GL_OUT_OF_MEMORY, que tiene que liberar otros recursos no utilizados (texturas, búferes, ...).

+0

gracias por las respuestas. por favor vea mi pregunta actualizada para comentarios sobre sus respuestas. –

+0

He actualizado mi respuesta, espero que esto ayude. –

+0

@Majid: ASTC aún no está disponible para nada. Para los sistemas basados ​​en Malí, creo que debe usar ETC, que también está * expuesto * en algunos otros sistemas (dependiendo del proveedor) –

Cuestiones relacionadas