我想使用多重采样抗锯齿并将我绘制的内容保存到 BMP。我使用 FBO 进行多重采样和普通 FBO。我参考了这篇文章:GL_framebuffer_multisample。
但是当我使用 glBlitFramebuffer 将数据从 FBO 复制到正常的 FBO 以进行多重采样时,会发生 OpenGL 错误。现在我在这里发布我的部分代码:
首先,创建两个 FBO:
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);//解除绑定
然后画一些东西:
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.So 我得出的结论:函数 glBlitFramebuffer 有问题。但是为什么?有没有设置错误?
更新:当我检查正常的 FBO m_frameBufferBlit时:
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?
怎么了?
回想一下帧缓冲完整性的条件可能很有用:
- 必须至少有一个图像附加到帧缓冲
- 所有附件必须完整
- 所有活动的绘制缓冲区都必须具有关联的图像
- 读取缓冲区(如果处于活动状态)必须具有关联的图像
- 所有附加的图像必须具有相同数量的样本
以及附加图像完整性的条件:
- 图像的宽度和高度必须为非零
- 图像内部格式必须与连接点匹配(例如:深度图像必须附加到深度附件)
请注意,这些规则是对实际规则的简化,实际规则稍微复杂一些。