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

  • 相关阅读:
    ini_set /ini_get函数功能-----PHP
    【转】那个什么都懂的家伙
    word 2007为不同页插入不同页眉页脚
    August 26th 2017 Week 34th Saturday
    【2017-11-08】Linux与openCV:opencv版本查看及库文件位置等
    August 25th 2017 Week 34th Friday
    August 24th 2017 Week 34th Thursday
    August 23rd 2017 Week 34th Wednesday
    August 22nd 2017 Week 34th Tuesday
    August 21st 2017 Week 34th Monday
  • 原文地址:https://www.cnblogs.com/chen9510/p/12438633.html
Copyright © 2011-2022 走看看