如何将图像数据的子矩形上传到OpenGLES 2帧缓冲纹理?

时间:2011-08-29 15:32:34

标签: opengl-es-2.0 framebuffer

在我的OpenGLES 2应用程序中(在Android 2.3上的SGX535上,并不重要),我有一个很大的纹理,我需要经常进行小的更新。我把它设置为一对FBO,在那里我渲染后缓冲区的更新,然后将整个后缓冲区作为纹理渲染到前缓冲区以“交换”它们。然后将前缓冲区用作场景中的其他位置。

更新有时是纯色子矩形,但大多数情况下,更新是原始图像数据,采用与纹理相同的格式,例如,新图像数据将作为RGB565和帧缓冲对象由RGB565纹理支持。

使用glTexSubImage2D()很慢,正如您所料,特别是在像SGX这样的延迟渲染器上。不仅如此,在FBO背面使用glTexSubImage2D最终会导致应用程序在SGX驱动程序的某处崩溃。

我尝试为每个子矩形创建新的纹理对象,调用glTexImage2D来初始化它们,然后将它们作为纹理四边形渲染到后缓冲区。在删除它们之前,我保留了两个FBO缓冲区交换的纹理对象,但显然不够长,因为当重新使用纹理ID时,它们保留了旧纹理的尺寸。

相反,我正在使用原始图像数据的整个缓冲区并将其转换为顶点和颜色的结构数组,如下所示:

struct rawPoint {
    GLfloat x;
    GLfloat y;
    GLclampf r;
    GLclampf g;
    GLclampf b;
};

然后我可以使用GL_POINTS将此数组渲染到后台缓冲区。对于RGB565数据的缓冲区,这意味着分配一个比原始数据大10倍的缓冲区,但它实际上比使用glTexSubImage2D()更快!

我无法将顶点或颜色保留为原始的无符号短格式,因为OpenGL ES 2仅在顶点属性和着色器制服中使用浮点数。我必须将每个像素作为一组单独的坐标提交,因为我没有几何着色器。最后,我不能使用EGL_KHR_gl_texture_2D_image扩展,因为我的平台不支持它!

必须有更好的方法来做到这一点!我正在燃烧大量的CPU周期,只是为了将图像数据转换成浪费的浮点颜色格式,这样GPU就可以将其转换回它开始的格式。

使用EGL Pbuffers会更好吗?我并不为这个前景感到兴奋,因为它需要上下文切换,我甚至不确定它会让我直接写入图像缓冲区。

1 个答案:

答案 0 :(得分:1)

我对图形有点新意,所以请大量使用它。

创建一个本机缓冲区(请参阅)纹理的大小 使用本机缓冲区创建EGL图像

eglCreateImageKHR(eglGetCurrentDisplay(), 
                  eglGetCurrentContext(),
                  EGL_GL_TEXTURE_2D_KHR, 
                  buffer, 
                  attr);

我知道这使用了EGL_GL_TEXTURE_2D_KHR。您确定您的平台不支持此功能吗?我正在开发一个使用SGX535的平台,我似乎也支持它。

之后,像往常一样绑定纹理。你可以记忆进入你的原生缓冲区,以便我很快地更新子矩形。

我意识到我正在回答一个月的问题,但如果您需要查看更多代码或其他内容,请告诉我。