Search code examples
opengl-esglteximage2d

Generating and updating 8-bit gray-scale texture in OpenGL ES 2.0


For an OpenGL texture cache I need to initialize a large (≥ 2048x2048) texture and then frequently update little sections of it.

The following (pseudo-)code works:

// Setup texture
int[] buffer = new int[2048*2048 / 4]; // Generate dummy buffer with 1 byte per pixel
int id = glGenTexture();
glBindTexture(GL_TEXTURE_2D, id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 2048, 2048, 0, GL_ALPHA, GL_UNSIGNED_BYTE, buffer);

// Perform update
glBindTexture(GL_TEXTURE_2D, id);
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, data);

But I find the totally unnecessary creation of a 4MB int-buffer a bit undesirable to say the least. So, I tried the following instead:

// Setup texture
int id = glGenTexture();
glBindTexture(GL_TEXTURE_2D, id);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 0, 0, 2048, 2048, 0);

This gave me a GL_INVALID_OPERATION error, which I believe is caused by the fact that the frame-buffer does not contain an alpha value, so rather than just setting that to 1, the call fails.

Next attempt:

// Setup texture
int id = glGenTexture();
glBindTexture(GL_TEXTURE_2D, id);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 0, 0, 2048, 2048, 0);

This works, but now my glTexSubImage2D call fails with GL_INVALID_OPERATION because it specifies GL_ALPHA instead of GL_LUMINANCE. So, I changed that as well to get:

// Perform update
glBindTexture(GL_TEXTURE_2D, id);
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);

And I changed my shader to read the value from the r rather than the a component.

This works on some devices, but on the iPhone 3GS, I still get the GL_INVALID_OPERATION error in the glTexSubImage2D call. Why? And how can I fix this? Is there some way, for example, to change the internal texture format? Or can I create some other framebuffer that does have an alpha component that I can use as the source for glCopyTexImage2D?


Solution

  • data can be NULL in your glTexImage2D() call if you just want to allocate an empty texture:

    data may be a null pointer. In this case, texture memory is allocated to accommodate a texture of width and height. You can then download subtextures to initialize this texture memory. The image is undefined if the user tries to apply an uninitialized portion of the texture image to a primitive.