OpenGL 中关于ImageTexture使用中遇到的两个问题 —— 快速清空 与 读写错误

 

  普通Texture无法在一个pass中完成读和写,且无法操作一个给定位置的数据,所以只能使用ImageTexture,使用时遇到了两个问题:

  1、快速清空

  ImageTexture 使用的是一张普通的 texture 纹理,texture 被包装为ImageTexture,故可以直接将texture清空即可。

    texture的清空方法:

    a、传值给texture(CPU-->GPU)、

void Transfer2Texture(float* data) {
    glBindTexture(GL_TEXTURE_2D, this->textureID);
    if (channels == 1)    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_R, GL_FLOAT, data);
    if (channels == 2)    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RG, GL_FLOAT, data);
    if (channels == 3)    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_FLOAT, data);
    if (channels == 4)    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, data);
    glBindTexture(GL_TEXTURE_2D, 0);
}

    b、绑定到FBO

    初始化时,调用glClearColor()glClearDepth()glClearStencil()分别设置清空后颜色缓存、深度缓存和模板缓存中的默认值。

    在每一帧渲染前,调用glClear()并传入GL_COLOR_BUFFER_BITGL_DEPTH_BUFFER_BITGL_STENCIL_BUFFER_BIT或它们的位组合进行对应缓存的清空操作。

    或者:在OpenGL3.0中支持了  void glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value)。

       buffer可以传入GL_COLORGL_DEPTHGL_STENCIL,以指明我们要清空哪种缓存;

      value指明了清空后的默认值;

      drawbuffer用于多输出缓存的情况。 

    以上方法这里都不适用:a方法需要CPU-->GPU传输数据很慢;b方法,texture已经被绑定封装给ImageTexture,可能不能再绑定到FBO

    后来查询到可以直接对ImageTexture清空数据!

    c、直接清空ImageTexture

    OpenGL需要版本4.4以上

void WKS::ImageTexture::InitData() {
    if (this->channels == 1)    glClearTexImage(this->textureID, 0, GL_R, GL_FLOAT, NULL);
    if (this->channels == 2)    glClearTexImage(this->textureID, 0, GL_RG, GL_FLOAT, NULL);
    if (this->channels == 3)    glClearTexImage(this->textureID, 0, GL_RGB, GL_FLOAT, NULL);
    if (this->channels == 4)    glClearTexImage(this->textureID, 0, GL_RGBA, GL_FLOAT, NULL);
}

 

  2、读写错误

    我需要计算场景的一张occlusion mask,一个像素对应多个物体(大于等于2个物体)则置 1, 否则置为 0

    故需要使用一张ImageTexture,当出现两个不同的物体ID则发现重叠了,故需要一个pass中的读和写同时存的操作。打印这张mask后发现,遮挡区域(1的位置)基本符合,但是会出现一些零星的 0 值,而且相机不移动时,mask也会变动(零星的0值会随机出现在其它位置)。我感觉是出现并行读写错误,但是OpenGL渲染场景是一个一个mesh绘制的,每渲染一个mesh是需要CPU向GPU发送一个Draw的命令的,故mesh之间应该本身就是有顺序关系的,不会同时执行出现错误。但我后来还是尝试着在每个mesh draw后面加了一个glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT)  ——针对image 读写的内存屏障,结果问题解决了,太意外了!由此我猜想mesh Draw之间不是完全顺序执行的,会同时执行,导致出现并行读写错误。

 

posted @ 2020-03-07 21:55  茶飘香~  阅读(186)  评论(0编辑  收藏