关于图形:glBlitFramebuffer导致OpenGL错误

glBlitFramebuffer cause OpenGL error

我想使用多重采样抗锯齿并保存我绘制到BMP的图像。我使用FBO进行多重采样和普通的FBO。我已经参考了本文:GL_framebuffer_multisample。

但是当我使用glBlitFramebuffer将数据从FBO进行多次采样复制到普通FBO时,就会发生OpenGL错误。现在我将部分代码发布在这里:

首先,创建两个FBO:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
glGenFramebuffers(1,&m_frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER,m_frameBuffer);

glGenRenderbuffers(1,&m_renderBufferColor);
glBindRenderbuffer(GL_RENDERBUFFER,m_renderBufferColor);
//在FBO里开启多重采样
glRenderbufferStorageMultisample(GL_RENDERBUFFER,4,
    GL_RGB,m_subImageWidth,m_subImageHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,
    GL_RENDERBUFFER,m_renderBufferColor);

glGenRenderbuffers(1,&m_renderBufferDepth);
glBindRenderbuffer(GL_RENDERBUFFER,m_renderBufferDepth);
glRenderbufferStorageMultisample(GL_RENDERBUFFER,4,
    GL_DEPTH_COMPONENT24,m_subImageWidth,m_subImageHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,
    GL_RENDERBUFFER,m_renderBufferDepth);

glBindFramebuffer(GL_FRAMEBUFFER,0);//解除绑定

//generate standard FBO for blitting
glGenFramebuffers(1,&m_frameBufferBlit);
glBindFramebuffer(GL_FRAMEBUFFER,m_frameBufferBlit);

glGenRenderbuffers(1,&m_renderBufferColorBlit);
glBindRenderbuffer(GL_RENDERBUFFER,m_renderBufferColorBlit);
glRenderbufferStorage(GL_RENDERBUFFER,GL_RGB,
    m_subImageWidth,m_subImageHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,
    GL_RENDERBUFFER,m_renderBufferColorBlit);

glGenRenderbuffers(1,&m_renderBufferDepthBlit);
glBindRenderbuffer(GL_RENDERBUFFER,m_renderBufferDepthBlit);
glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT24,
    m_subImageWidth,m_subImageHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,
    GL_RENDERBUFFER,m_renderBufferDepth);

glBindFramebuffer(GL_FRAMEBUFFER,0);//解除绑定

然后画点东西:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
glBindFramebuffer(GL_FRAMEBUFFER,m_frameBuffer);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
{
    cout <<"The frame buffer status is not complete!" << endl;
    return;
}

drawing();//draw something
glBindFramebuffer(GL_FRAMEBUFFER,0);

    int temp1 = GLUtils::checkForOpenGLError(__FILE__,__LINE__);
    //blitting
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER,m_frameBufferBlit);
    glBindFramebuffer(GL_READ_FRAMEBUFFER,m_frameBuffer);

    int temp2 = GLUtils::checkForOpenGLError(__FILE__,__LINE__);
    glBlitFramebuffer(0,0,m_subImageWidth,m_subImageHeight,
        0,0,m_subImageWidth,m_subImageHeight,
        GL_COLOR_BUFFER_BIT,GL_LINEAR);
    int temp3 = GLUtils::checkForOpenGLError(__FILE__,__LINE__);
    glBindFramebuffer(GL_READ_FRAMEBUFFER,0);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER,0);

    //glBindFramebuffer(GL_FRAMEBUFFER,m_frameBuffer);
    glBindBuffer(GL_PIXEL_PACK_BUFFER,m_subImageBuffer[i]);
    glPixelStorei(GL_PACK_ALIGNMENT,1);

    glBindFramebuffer(GL_FRAMEBUFFER,m_frameBufferBlit);
    //注意:以BGR的顺序读取
    glReadPixels(0,0,m_subImageWidth,m_subImageHeight,
        GL_BGR,GL_UNSIGNED_BYTE,bufferOffset(0));
    int temp4 = GLUtils::checkForOpenGLError(__FILE__,__LINE__);
    m_subPixels[i] = static_cast<GLubyte*>(glMapBuffer(GL_PIXEL_PACK_BUFFER,GL_READ_ONLY));
    if (m_subPixels[i] == NULL)
    {
        cout <<"NULL pointer" << endl;
    }
    gltGenBMP(subImageFile[i],GLT_BGR,m_subImageWidth,m_subImageHeight,m_subPixels[i]);
    glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
    glBindBuffer(GL_PIXEL_PACK_BUFFER,0);

    glBindFramebuffer(GL_FRAMEBUFFER,0);

函数GLUtils :: checkForOpenGLError用于检查是否发生OpenGL错误(返回1表示发生了错误)绘图是用于渲染某些东西,而gltGenBMP函数是将数据另存为BMP,它们都工作良好,我发现temp1和temp2为0,temp3和temp4为1.所以我得出一个结论:glBlitFramebuffer函数有问题,但为什么设置有问题?

更新:
当我检查正常的FBO m_frameBufferBlit时:

1
2
3
4
5
6
7
glBindFramebuffer(GL_DRAW_FRAMEBUFFER,m_frameBufferBlit);
status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
{
    cout <<"The frame buffer status is not complete!" << endl;
    return;
}

我发现它不完整。所以我没有正确创建FBO吗?

有什么问题?


回忆一下帧缓冲区完整性的条件可能很有用:

  • 至少必须有一个图像附加到帧缓冲区
  • 所有附件必须完整
  • 所有活动绘图缓冲区必须具有关联的图像
  • 读取缓冲区(如果处于活动状态)必须具有关联的映像
  • 所有附加的图像必须具有相同数量的样本

以及附加图像完整性的条件:

  • 图片的宽度和高度必须为非零
  • 图片内部格式必须与附件点匹配
    (例如:深度图像必须附加到深度附件中)

请注意,这些规则是实际规则的简化,而实际规则则稍微复杂一些。