pianka
pianka

Reputation: 140

OpenGL ES Android - Texture not loaded (rendered black)

As in the title, I'm using OpenGL ES (2) on Android (7.0). Apparently, though, I have some problems when trying to load a texture from the asset folder. This is the code I'm using

public static int loadTexture(final AssetManager assetManager, final String img)
{
    final int[] textureHandle = new int[1];
    glGenTextures(1, textureHandle, 0);

    if(textureHandle[0] == 0)
        throw new RuntimeException("Error loading texture");

    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inScaled = false;

    try
    {
        final Bitmap bitmap = BitmapFactory.decodeStream(assetManager.open(img));
        glBindTexture(GL_TEXTURE_2D, textureHandle[0]);

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

        GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);

        bitmap.recycle();
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }

    textures.put(img, textureHandle[0]);

    return textureHandle[0];
}

This is called from onSurfaceCreated as I know I need a running OpenGL context

Most of the time this works and gives me this result

working texture

but a considerable number of other times I get this

enter image description here

No Exception is thrown.

I know the problem is not depending on the 3D model nor the texture because I've tried other ones. The only thing I can do when this happens is to restart my App a couple of times.

I've tried googling around but with no results. I know I could try to implement another loading function, but first I'd like to understand why this is not ok and where it's not working.


If you think this could depends on the code I'm using to render the scene here it is (no VAOs because I need to support older devices and OpenGL ES 2):

glBindBuffer(GL_ARRAY_BUFFER, model.getCoordsVBO());
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(0);

glBindBuffer(GL_ARRAY_BUFFER, model.getTextureVBO());
glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(1);

glBindBuffer(GL_ARRAY_BUFFER, model.getNormalsVBO());
glVertexAttribPointer(2, 3, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(2);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, entity.getTexture());
loadFloat(loc_textureSampler, 0);

if(model.getIndicesBuffer() != null)
{
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model.getIndicesVBO());
    glDrawElements(GL_TRIANGLES, model.getVertexCount(), GL_UNSIGNED_INT, 0);
}
else
    glDrawArrays(GL_TRIANGLES, 0, model.getVertexCount());

glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

Upvotes: 3

Views: 238

Answers (1)

pianka
pianka

Reputation: 140

What I didn't say (because I thought it was irrelevant) is that I had a little more code ad the top of the function...

if(textures.containsKey(img))
    return textures.get(img);

and at the bottom

textures.put(img, textureHandle[0]);

I thought it was intelligent to keep track of the textures, so I could have called this load function anytime I needed a texture and if I had already loaded it, it would have returned it without loading again.

This could work on a desktop application, but I haven't considered that on Android the garbage collector could delete the texture from OpenGL when I exit the app so that when the activity restarts it wouldn't be there anymore.

Removing that HashMap solved the problem, demonstrating that the actual reading and loading code had nothing to do with that black thing.

Upvotes: 1

Related Questions