2

I'm experimenting with array textures in OpenGL ES 3. I'm trying to render different textures onto different cubes that I've batched rendered. But the cubes only show up as black.

I looked in the Logcat messages and narrowed down the issue to when I'm calling glTexStorage3D. This is the message I'm getting:

08-14 10:24:00.332 17416-17429/? W/Adreno-ES20﹕ core_glTexStorage3D:265: GL_INVALID_OPERATION

According to the documentation the error occurs when

GL_INVALID_OPERATION is generated if the default texture object is curently bound to target.

GL_INVALID_OPERATION is generated if the texture object curently bound to target already has GL_TEXTURE_IMMUTABLE_FORMAT set to GL_TRUE.

GL_INVALID_OPERATION is generated if target is GL_TEXTURE_2D_ARRAY and levels is greater than ⌊log2(max(width, height))⌋+1.

I checked for these conditions and printed to logcat:

08-14 10:24:00.332 17416-17429/? D/a﹕ immutable is gl false

08-14 10:24:00.332 17416-17429/? D/a﹕ texture binding 2d array: 0

08-14 10:24:00.332 17416-17429/? D/a﹕ texture binding 2d array after bind method: 1

08-14 10:24:00.332 17416-17429/? D/a﹕ immutable after binding is gl false

08-14 10:24:00.332 17416-17429/? W/Adreno-ES20﹕ : GL_INVALID_OPERATION

According to the logs, the first two conditions don't match. The width, height, and level that I'm passing are all 1, so the third condition shouldn't match either.

What's causing the invalid operation error? Also, is the invalid operation error the cause of my black textures, or is it not related?

Here's how I'm loading the array textures:

int width = 1;
int height = 1;
public int generateTextureArray(int res[]) {
    int texArray[] = new int[1];
    int params[] = new int[2];

    GLES30.glGetTexParameteriv(GLES30.GL_TEXTURE_2D_ARRAY, GLES30.GL_TEXTURE_IMMUTABLE_FORMAT, params, 0);
    if (params[0] == GLES30.GL_TRUE)
        Log.d("a", "immutable is gl true");
    else
        Log.d("a", "immutable is gl false");

    GLES30.glGetIntegerv(GLES30.GL_TEXTURE_BINDING_2D_ARRAY, params, 1);
    Log.d("a", "texture binding 2d array: " + params[1]);

    GLES30.glGenTextures(1, texArray, 0);
    GLES30.glBindTexture(GLES30.GL_TEXTURE_2D_ARRAY, texArray[0]);

    if (texArray[0] != 0) {

        GLES30.glGetIntegerv(GLES30.GL_TEXTURE_BINDING_2D_ARRAY, params, 1);
        Log.d("a", "texture binding 2d array after bind method: " + params[1]);

        GLES30.glGetTexParameteriv(GLES30.GL_TEXTURE_2D_ARRAY, GLES30.GL_TEXTURE_IMMUTABLE_FORMAT, params, 0);
        if (params[0] == GLES30.GL_TRUE)
            Log.d("a", "immutable after binding is gl true");
        else
            Log.d("a", "immutable after binding is gl false");

        GLES30.glTexStorage3D(GLES30.GL_TEXTURE_2D_ARRAY, 1, GLES30.GL_RGBA, width, height, res.length);

        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = false;   // No pre-scaling

        for (int i = 0; i < res.length; i++) {
            Bitmap bitmap = BitmapFactory.decodeResource(surfaceView.getResources(), res[i], options);
            ByteBuffer texBuffer = ByteBuffer.allocateDirect(bitmap.getHeight() * bitmap.getWidth() * 4);
            bitmap.copyPixelsToBuffer(texBuffer);
            texBuffer.position(0);

            GLES30.glTexSubImage3D(GLES30.GL_TEXTURE_2D_ARRAY, 0, 0, 0, i, width, height, 1,
                    GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, texBuffer);

            bitmap.recycle();
        }

        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D_ARRAY, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D_ARRAY, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D_ARRAY, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D_ARRAY, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE);
    } else {
        throw new RuntimeException("Error loading texture");
    }

    return texArray[0];
}
Reto Koradi
  • 53,228
  • 8
  • 93
  • 133
yendisng
  • 23
  • 5

1 Answers1

0

It's possible that there's something else going on as well, but you should actually get a GL_INVALID_ENUM error from your glTexStorage3D() call:

GLES30.glTexStorage3D(GLES30.GL_TEXTURE_2D_ARRAY, 1, GLES30.GL_RGBA,
                      width, height, res.length);

Only sized internal formats are supported for glTexStorage3D(), which means that GL_RGBA is not a valid format. If you want 8 bits per component, the correct call is:

GLES30.glTexStorage3D(GLES30.GL_TEXTURE_2D_ARRAY, 1, GLES30.GL_RGBA8,
                      width, height, res.length);

This doesn't explain the GL_INVALID_OPERATION, but I would certainly try to fix this, and see if that gets it working.

Reto Koradi
  • 53,228
  • 8
  • 93
  • 133