2012-03-13 8 views
5

Actualmente estoy implementando un visor 3D que básicamente representa un subconjunto de todas las imágenes que el usuario tiene en su tarjeta SD. El producto más cercano a juego yo pensaría sería CoolIris:Android OpenGL textures: creación y eliminación sobre la marcha

enter image description here

Simplemente muestran una tabla de desplazamiento de las baldosas N en la pantalla, mostrando cada una diferentes imágenes, con nuevas baldosas de entrar en la pantalla y mostrando nuevas imágenes.

Ahora para mi problema: Tengo el programa funcionando y representando muy bien los quads. Cuando un quad sale de la pantalla, se recicla/libera. Y los nuevos quads se siguen agregando a la placa de mosaico antes de que entren en la pantalla.

Dado que puede haber cientos de imágenes, las texturas deben crearse y eliminarse sobre la marcha (para que no nos quedemos sin memoria). El problema que tengo es que después de eliminar las texturas, las texturas recién creadas parecen obtener algunos ID de otras texturas actualmente en uso.

Mi bucle de renderizado se ve así:

void render(GL10 gl) { 
    0. Move the camera 

    // Tile board maintenance 
    1. Remove tiles out of screen 
    2. Add new tiles which are about to enter screen 

    // Texture handling 
    3. glDeleteTextures on all unused textures followed by glFlush 
    4. For newly used images 
    - Create corresponding Bitmap 
    - Create the OpenGL texture, followed by glFlush 
    - Release the Bitmap 

    // Rendering 
    5. Render the tile (using a textured quad) 

} 

Para dar una mejor idea de cómo están organizados los datos, aquí es una visión general de las clases:

TileBoard { 
    Image[] allImages; 
    Tile[] board; 
} 

Tile { 
    Image image; 
} 

Image { 
    String path; 
    int textureId; 
    int referenceCount; 
} 

código de creación de Textura:

protected void loadSingleTexture(GL10 gl, long objectId, Bitmap bmp) { 
    int[] textures = new int[1]; 
    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_LINEAR); 
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); 
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0); 
    gl.glFlush(); 

    if (bmp != null) bmp.recycle(); 

    if (listener != null) listener.onTextureLoaded(gl, objectId, textures[0]); 
} 

Código de eliminación de textura:

// pendingTextureUnloads is a Set<Integer> 
if (pendingTextureUnloads.size() > 0) { 
    int[] textureIds = new int[pendingTextureUnloads.size()]; 
    int i = 0; 
    Iterator<Integer> it = pendingTextureUnloads.iterator(); 
    while (it.hasNext()) { 
    textureIds[i] = it.next(); 
    } 

    gl.glDeleteTextures(textureIds.length, textureIds, 0); 
    gl.glFlush(); 
} 
+0

¿Has intentado llamar a glGetError en cualquier lugar? – Tim

Respuesta

5

He resuelto el problema: el problema es que tienes que mantener el conjunto de texturas pasado a glGenTextures y reutilizarlo.

Aquí está el resumen modificado para los que van a tener el mismo problema:

Image { 
    String path; 
    int[] textureIds; 
    int referenceCount; 
} 

Textura código de creación:

// Notice that I don't allocate the int[] at the beginning but use the one of the image 
protected void loadSingleTexture(GL10 gl, Image img, Bitmap bmp) { 
    gl.glGenTextures(1, img.textureIds, 0); 
    gl.glBindTexture(GL10.GL_TEXTURE_2D, img.textureIds[0]); 
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); 
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); 
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0); 
    gl.glFlush(); 

    if (bmp != null) bmp.recycle(); 
} 

Textura código de eliminación:

foreach Image img { 
    gl.glDeleteTextures(img.textureIds.length, img.textureIds, 0); 
} 
gl.glFlush(); 
+0

Sería bueno si alguien sabe cómo funciona todo esto en detalle y por qué la misma matriz tiene que ser utilizada en este caso. He visto muchos otros ejemplos cuando las texturas se generan utilizando múltiples matrices de 1 dim. Además, ¿no inicias la matriz antes de llamar a glGenTextures? –

4

que sé dijiste que resolviste tu problema, pero creo que noté tu error en el primer fragmento de código. Observe el ciclo while en su código de eliminación de texturas, no está aumentando el índice i para su matriz, por lo que continuamente asignará el primer índice hasta llegar a la última entrada en pendingTextureUnloads, el resto de los índices será 0 (nulo) . Eso podría ser problemático.

Y, por cierto, tengo la generación de texturas funcionando al no reutilizar la matriz, solo devolviendo el índice que fue generado por glGenTextures. Mi código corresponde a la línea igual a la tuya, excepto crear una nueva matriz int al comienzo del método y devolver el int en el primer índice al final. Tu código para la generación de texturas debería funcionar, el error fue solo en la eliminación de texturas.

+0

Buena captura. +1 :) –

Cuestiones relacionadas