OpenGL glBlitFramebuffer不会正确地对颜色和深度缓冲区进行blit。结果从glReadPixel验证

时间:2015-05-22 17:22:10

标签: c++ opengl multisampling

我很难使用OpenGL函数glBlitFramebuffer。在文档中,它表示它支持blitting颜色和深度缓冲区。但是,在实践中却没有。我在Macbook AIR 13英寸,Intel HD Graphics 5000 1536 MB。

我需要从http://ake.in.th/2013/04/02/offscreening-and-multisampling-with-opengl/

进行多重采样

我的多重采样级别是4(AA_LEVEL = 4),我的OpenGL版本是:3.2核心配置文件。这就是我在做的事情:

  1. 创建多样本AA帧缓冲区。

    glGenFramebuffers( 1, &_offscreenBufferHandle );
    glBindFramebuffer( GL_FRAMEBUFFER, _offscreenBufferHandle );
    
    glGenRenderbuffers(1, &_depthRenderbuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderbuffer);
    glRenderbufferStorageMultisample(GL_RENDERBUFFER, AA_LEVEL, GL_DEPTH_COMPONENT16, srcWidth_, srcHeight_);
    glBindRenderbuffer(GL_RENDERBUFFER, 0);
    
    glGenRenderbuffers(1, &_aaColorbuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, _aaColorbuffer);
    glRenderbufferStorageMultisample(GL_RENDERBUFFER, AA_LEVEL, GL_RGBA, srcWidth_, srcHeight_);
    glBindRenderbuffer(GL_RENDERBUFFER, 0);
    
  2. 创建目标帧缓冲区

    glGenFramebuffers( 1, &_outputBufferHandle );
    glBindFramebuffer( GL_FRAMEBUFFER, _outputBufferHandle );
    
    glGenRenderbuffers(1, &_outputColorbuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, _outputColorbuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, srcWidth_, srcHeight_);
    glBindRenderbuffer(GL_RENDERBUFFER, 0);
    
    glGenRenderbuffers(1, &_outputDepthbuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, _outputDepthbuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, srcWidth_, srcHeight_);
    glBindRenderbuffer(GL_RENDERBUFFER, 0);
    
  3. 使用颜色和深度缓冲区绘制内容

    glBindFramebuffer( GL_DRAW_FRAMEBUFFER, _offscreenBufferHandle );
    glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _aaColorbuffer);
    glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderbuffer);  
    //next 
    DrawStuff();
    
  4. 将多样本AA帧缓冲区blit到目标帧缓冲区中。

    glBindFramebuffer( GL_READ_FRAMEBUFFER, _offscreenBufferHandle );
    glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _aaColorbuffer);
    glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderbuffer);
    
     glBindFramebuffer( GL_DRAW_FRAMEBUFFER, _outputBufferHandle );
     glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _outputColorbuffer);
     glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _outputDepthbuffer);
    
     if( glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE &&
    glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE ) {
        //do blitting here
        glBlitFramebuffer(0, 0, srcWidth_, srcHeight_, 0, 0, srcWidth_, srcHeight_, GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT, GL_NEAREST);
     }
    
  5. 从目标帧缓冲区中读取像素并进行一些后期处理

    //then blit it to pixels buffer
    glBindFramebuffer(GL_READ_FRAMEBUFFER, _outputBufferHandle);
    glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _outputColorbuffer);
    glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _outputDepthbuffer);
    readParam("temp");
    
    GLenum framebufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if( framebufferStatus == GL_FRAMEBUFFER_COMPLETE ) {
        glReadBuffer(GL_COLOR_ATTACHMENT0);
        //getGLErr("GL_COLOR_ATTACHMENT0");
        glReadPixels(0, 0, srcWidth_, srcHeight_, GL_BGR, GL_UNSIGNED_BYTE, pixels);
    }
    
  6. 然而结果只有颜色缓冲液成功印迹,没有深度缓冲。

    如果我禁用多重采样,通过更改我的AA_LEVEL = 0,并替换删除步骤4,用以下代码替换步骤5直接从_offscreenBufferHandle读取,结果看起来正确。

    glBindFramebuffer(GL_READ_FRAMEBUFFER, _offscreenBufferHandle);
    glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _aaColorbuffer);
    glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderbuffer);
    GLenum framebufferStatus = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
    if( framebufferStatus == GL_FRAMEBUFFER_COMPLETE ) {
        glReadPixels(0, 0, srcWidth_, srcHeight_, GL_BGR, GL_UNSIGNED_BYTE, pixels);
    }
    

    很多帖子都指向类似的问题,我很困惑这是一个图形卡问题,还是我一直在做的事情是错误的。

    https://gamedev.stackexchange.com/questions/68290/fbo-blit-depth-buffer-to-screen

    https://www.opengl.org/discussion_boards/showthread.php/176317-Framebuffer-not-bliting-depth-buffer

    在这些文章中,这意味着我需要绘制纹理四边形,而不是从读取缓冲区到绘制缓冲区执行blit。那太麻烦了。

0 个答案:

没有答案