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吗?
有什么问题?
回忆一下帧缓冲区完整性的条件可能很有用:
- 至少必须有一个图像附加到帧缓冲区
- 所有附件必须完整
- 所有活动绘图缓冲区必须具有关联的图像
- 读取缓冲区(如果处于活动状态)必须具有关联的映像
- 所有附加的图像必须具有相同数量的样本
以及附加图像完整性的条件:
- 图片的宽度和高度必须为非零
-
图片内部格式必须与附件点匹配
(例如:深度图像必须附加到深度附件中)
请注意,这些规则是实际规则的简化,而实际规则则稍微复杂一些。