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];
}