4
votes

I'm trying to render my scene to my FBO and then render it in a smaller size in corner of the screen. It works fine, but only if the FBO has only Color Texture. When I try to attach Depth Texture or Depth Buffer to it, it draws single pixels of my screen. Here are some screens:

FBO with Color Texture
FBO with Color Texture

FBO with Color and Depth Texture
FBO with Color and Depth Texture

Here's my FBO class code:

FrameBuffer::FrameBuffer()
{
    GLcall( glGenFramebuffers(1, &m_id) );

    GLcall( glBindFramebuffer(GL_FRAMEBUFFER, m_id) );
    GLcall( glDrawBuffer(GL_COLOR_ATTACHMENT0) );

    GLcall( glBindFramebuffer(GL_FRAMEBUFFER, 0) );
}

void FrameBuffer::attachTexture(const unsigned int width, const unsigned int height)
{
    GLcall( glBindFramebuffer(GL_FRAMEBUFFER, m_id) );

    m_textureAttachmentsIDs.push_back(0);
    GLcall( glGenTextures(1, &m_textureAttachmentsIDs[ m_textureAttachmentsIDs.size() - 1 ]) );

    GLcall( glBindTexture(GL_TEXTURE_2D, m_textureAttachmentsIDs[ m_textureAttachmentsIDs.size() - 1 ]) );
    GLcall( glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr) );
    GLcall( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) );
    GLcall( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) );
    GLcall( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) );
    GLcall( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) );

    GLcall( glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_textureAttachmentsIDs[ m_textureAttachmentsIDs.size() - 1 ], 0) );

    GLcall( glBindTexture(GL_TEXTURE_2D, 0) );
    GLcall( glBindFramebuffer(GL_FRAMEBUFFER, 0) );
}

void FrameBuffer::attachDepthTexture(const unsigned int width, const unsigned int height)
{
    GLcall( glBindFramebuffer(GL_FRAMEBUFFER, m_id) );

    GLcall( glGenTextures(1, &m_depthTextureAttachmentID) );

    GLcall( glBindTexture(GL_TEXTURE_2D, m_depthTextureAttachmentID) );
    GLcall( glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr) );
    GLcall( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) );
    GLcall( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) );
    GLcall( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) );
    GLcall( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) );
    GLcall( glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_ALPHA) );

    GLcall( glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthTextureAttachmentID, 0) );

    GLcall( glBindTexture(GL_TEXTURE_2D, 0) );
    GLcall( glBindFramebuffer(GL_FRAMEBUFFER, 0) );
}

void FrameBuffer::attachDepthBuffer(const unsigned int width, const unsigned int height)
{
    GLcall( glBindFramebuffer(GL_FRAMEBUFFER, m_id) );

    GLcall( glGenRenderbuffers(1, &m_depthBufferAttachmentID) );

    GLcall( glBindRenderbuffer(GL_RENDERBUFFER, m_depthBufferAttachmentID) );
    GLcall( glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height) );
    GLcall( glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthBufferAttachmentID) );

    GLcall( glBindRenderbuffer(GL_RENDERBUFFER, 0) );
    GLcall( glBindFramebuffer(GL_FRAMEBUFFER, 0) );
}


void FrameBuffer::bind(const unsigned int width, const unsigned int height) const
{
    GLcall( glBindFramebuffer(GL_FRAMEBUFFER, m_id) );
    GLcall( glViewport(0, 0, width, height) );
}

void FrameBuffer::unbind(const Window& window) const
{
    GLcall( glBindFramebuffer(GL_FRAMEBUFFER, 0) );
    GLcall( glViewport(0, 0, window.getWidth(), window.getHeight()) );
}

Here is code that sets up my FBO and Sprite to render a texture to:

FrameBuffer testFBO;
testFBO.attachTexture(320, 180);
testFBO.attachDepthTexture(320, 180);

Layer2D layer(window);
Sprite2D screenSprite(vector2(400.0f, 600.0f), vector2(640.0f, 360.0f));
layer.addSprite(&screenSprite);

Texture screenTexture(testFBO.getTextureAttachments()[0], 320, 180);

And here's the code which handles rendering:

testFBO.bind(320, 180);
rr.render(cam);
testFBO.unbind(window);

screenSprite.setTexture(&screenTexture);

rr.render(cam);
layer.render();

I'm not posting rendering code, because it renders everything fine if I don't attach Depth Texture or Depth Buffer.

And yes, I am clearing depth buffer:

GLcall( glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) );

GLcall() function checks for any OpenGL errors and there aren't any when I'm executing this code.

Thanks in advance.

1
And here's texture line of code: Texture screenTexture(testFBO.getColorTexture(), 320, 180);Smile
Have you tried to clear the depthbuffer?Thomas
Check your framebuffer for completeness. And try a depth buffer format which is actually required to be supported by a GL implementation, GL_DEPTH_COMPONENT32 isn't.derhass
@Smile Do you clear the separate depth buffer of the framebuffer too?Rabbid76
Clearing the Depth Buffer was the fix. Thank you Thomas and @Rabbid76Smile

1 Answers

1
votes

The fix was to clear FBO's Depth Buffer.

testFBO.bind(320, 180);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
rr.render(cam);
testFBO.unbind(window);

I only cleared Depth Buffer of default FBO.