在 OpenGL ES 2.0 中生成和更新 8 位灰度纹理

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

对于 OpenGL 纹理缓存,我需要初始化一个大的 (≥ 2048x2048) 纹理,然后经常更新它的小部分。

以下(伪)代码有效:

// 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);

但我发现完全没有必要创建一个 4MB 的 int-buffer 至少可以说有点不受欢迎。所以,我尝试了以下方法:

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

这给了我一个 GL_INVALID_OPERATION 错误,我认为这是由于帧缓冲区不包含 alpha 值这一事实引起的,因此调用失败而不是仅仅将其设置为 1。

下一次尝试:

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

这有效,但现在我的 glTexSubImage2D 调用失败并显示 GL_INVALID_OPERATION,因为它指定 GL_ALPHA 而不是 GL_LUMINANCE。所以,我也改变了它以获得:

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

我更改了着色器以从 r 而不是 a 组件读取值。

这在某些设备上有效,但在 iPhone 3GS 上,我仍然在 glTexSubImage2D 调用中遇到 GL_INVALID_OPERATION 错误。为什么?我该如何解决这个问题?例如,有什么方法可以改变内部纹理格式吗?或者我可以创建其他一些具有 alpha 组件的帧缓冲区,我可以将其用作 glCopyTexImage2D 的源吗?

如果您只想分配一个空纹理,

data 可以是 NULL 在您的 glTexImage2D() 调用中:

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.