• 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之间不是完全顺序执行的,会同时执行,导致出现并行读写错误。

  • 相关阅读:
    Node.js模块风格在浏览器中的尝试
    Node.js的模块写法入门
    JavaScript中“+”的陷阱(续)
    Firefox/Chrome/Safari的中可直接使用$/$$函数进行调试
    使用r.js压缩整个项目的JavaScript文件
    拥抱模块化的JavaScript
    图片播放(3)
    JavaScript中“+”的陷阱
    仅IE6/7浏览器SPAN元素包含块级元素会使SPAN的背景色显示
    JavaScript模态对话框类(拖拽时动画)
  • 原文地址:https://www.cnblogs.com/chen9510/p/12438633.html
Copyright © 2020-2023  润新知