Search code examples
c++qtopengldepth-testing

Depth Testing not working when using QOpenGLFramebufferObject


I met the problem where the depth testing not working when I use the QOpenGLFramebufferObject.

But It worked if I copy default framebuffer to the QOpenGLFramebufferObject using glBlitFramebuffer. I don't know the reason.

Here is the code:

void SceneView3D::paintGL()
{
    QOpenGLContext *ctx = QOpenGLContext::currentContext();

    QOpenGLFramebufferObjectFormat fboFormat;
    fboFormat.setSamples(0);
    fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
    m_framebuffer = new QOpenGLFramebufferObject(this->width(), this->height(), fboFormat);

    m_framebuffer->bind();
// --------------------------------------
// draw scene here
//-------------------------------------
    QImage image = m_framebuffer->toImage();
    image.save(R"(image.jpg)");
    m_framebuffer->release();
}

I created the QOpenGLFramebufferObject and already set depth attachment, but nothing drawing in the output image. It seems the color attachment got lost.

But If I add those code before drawing, It worked.

glBindFramebuffer(GL_READ_FRAMEBUFFER, defaultFramebufferObject());
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer->handle());
ctx->extraFunctions()->glBlitFramebuffer(0, 0, width(), height(), 0, 0, m_framebuffer->width(), m_framebuffer->height(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);

So, I don't know why the depth info in defaultFramebufferObject but not in m_framebuffer where I created.

Any ideas to figure it out?


Solution

  • You have to clear the depth buffer and the color buffer of the framebuffer after binding it and before drawing to it.
    It the depth buffer is not cleared, then the Depth Test will fail and nothing is drawn at all.

    m_framebuffer->bind();
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    
    // draw scene here
    // [...]
    
    QImage image = m_framebuffer->toImage();
    image.save(R"(image.jpg)");
    m_framebuffer->release();
    

    Note, the depth buffer of the default framebuffer is cleared (probably). Copying the the "cleared" depth buffer, to the depth buffer of the framebuffer, "clears" it, too.