最近学习了一下OpenGL的相关知识,在此记录一下FBO的使用和Qt下离屏渲染的注意事项。
有关FBO的介绍在很多博客中都有介绍,本文就不再赘述了,FBO初始化代码:
glGenFramebuffers(1, &m_frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, m_frameBuffer);
glGenTextures(1, &m_textureFBO);
glBindTexture(GL_TEXTURE_2D, m_textureFBO);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_width, m_height, 0, GL_BGRA, GL_UNSIGNED_BYTE, nullptr);//TODO
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_textureFBO, 0);
glGenRenderbuffers(1, &m_RBO);
glBindRenderbuffer(GL_RENDERBUFFER, m_RBO);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_width, m_height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_RBO);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
qDebug() << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" ;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
成功将图像绘制到自己创建的FBO中的纹理后,如何将此纹理再渲染到默认的FBO中显示出来,有一个地方需要注意,否则会渲染失败。paintGL()函数如下:
glBindFramebuffer(GL_FRAMEBUFFER, m_frameBuffer);
glEnable(GL_DEPTH_TEST);
glClearColor(0.5f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
m_shaderProgram->bind();
glBindVertexArray(m_VAO);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_texture);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
m_shaderProgram->release();
/********** 关键之处 ***********/
//通过api获取qt绘制时默认的framebuffer编号,此编号不一定为0
//但是glfw或glut中framebuffer默认编号是0
GLuint fb = context()->defaultFramebufferObject();
glBindFramebuffer(GL_FRAMEBUFFER, fb);
glDisable(GL_DEPTH_TEST);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, m_width, m_height);
m_programScreen->bind();
glBindVertexArray(m_fVAO);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, m_textureFBO);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
m_programScreen->release();
如果是用glfw或glut,绑定默认Framebuffer时,通常是用:
glBindFramebuffer(GL_FRAMEBUFFER, 0);
但在Qt中,当前Framebuffer的id不一定是0,而很多博客或代码中都是直接绑定0,往往就是因为绑定的id不对,导致渲染失败。楼主就是在这里耽误了好久,以为是FBO初始化过程有错误,于是不停的改,但就是不能解决问题。
正确的方法是:
GLuint fb = context()->defaultFramebufferObject();
glBindFramebuffer(GL_FRAMEBUFFER, fb);
在paintGL()中,通过context()->defaultFramebufferObject()获取当前Framebuffer的id,然后glBindFramebuffer()这个ID号。