PDA

View Full Version : FBO fails after rendering to the screen



littlemanrkc
10-08-2009, 12:22 PM
I have an MFC application that needs to save off screen captures every time it is redrawn. I want this to happen even when the windows is hidden or minimized, so I've begun to delve into the world of frame buffer objects. What I have works properly until I display something on the screen. After that glCheckFramebufferStatus(GL_FRAMEBUFFER) always returns 0. Here's a rough cut of my code:

Draw ()
{
// Set our current render target based on window visibility
if (bRenderToScreen)
{
wglMakeCurrent (m_hDC, m_hRC)
}
else
{
glBindFramebuffer (GL_FRAMEBUFFER, m_uiOffscreenFBO);
glDrawBuffer (GL_DEPTH_ATTACHMENT_EXT);
glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
eStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
// eStatus is always 0x0 after making a single call to the Draw() function with bRenderToScreen=true. It is set to GL_FRAMEBUFFER_COMPLETE every time until that happens.
}

// Drawing code goes here...

// Save off a screenshot
glReadPixels (0, 0, width (), height(), GL_RGB, GL_UNSIGNED_BYTE, pucRGBdata);
SaveImage (pucImage);

// Undo our current render target
if (bRenderToScreen)
{
SwapBuffers (m_hDC);
wglMakeCurrent (m_hDC, NULL);
}
else
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDrawBuffer (GL_BACK);
}
}


So basically, my frame buffer fails to work properly after I've made one call to the Draw() function when bRenderToScreen is set to true. Does anyone have any ideas what might be wrong?

ZbuffeR
10-08-2009, 01:31 PM
Mipmaps ?

littlemanrkc
10-08-2009, 03:12 PM
I'm using mipmaps. Here's my code that initializes the FBO. I assumed this wasn't the problem since it works correctly the first time time I call Draw() without having rendered anything to the screen. Of course, I could be wrong about this assumption...

GLuint uiOffscreenTexture;
GLuint uiOffscreenRenderer;

// Create the texture that we will render to
glGenTextures (1, &uiOffscreenTexture);
glBindTexture (GL_TEXTURE_2D, uiOffscreenTexture);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, width(), height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);

// attach the texture to FBO color attachment point
glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D, m_uiOffscreenFBO, 0);

// create a renderbuffer object to store depth info
glGenRenderbuffers (1, &uiOffscreenRenderer);
glBindRenderbuffer (GL_RENDERBUFFER, uiOffscreenRenderer);
glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width(), height());

// attach the renderbuffer to depth attachment point
glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER, m_uiOffscreenFBO);

glBindTexture (GL_TEXTURE_2D, 0);
glBindRenderbuffer (GL_RENDERBUFFER, 0);

ZbuffeR
10-08-2009, 03:45 PM
Not sure but I think GL_GENERATE_MIPMAP is obsolete, and does not work with FBO.
Instead, try explicit mipmap generation each time the texture has been rendered into, with :
glGenerateMipmapEXT(GL_TEXTURE_2D);

... or at least test without mipmaps :
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

littlemanrkc
10-08-2009, 04:06 PM
I tested it without mipmaps and saw the same [bad] result. I also tested it generating the mipmaps and calling glGenerateMipmapEXT(GL_TEXTURE_2D), with the same result. My application doesn't require mipmaps, so I can leave them disabled.

Is there anything in the OpenGL state that could be getting messed up from rendering to the screen that I'm not setting back to what I'm supposed to? I assumed that all I needed was to bind the fbo, and set the drawbuffers for the texture and renderbuffer, and then I would be good to go.

littlemanrkc
10-09-2009, 06:56 AM
I found the problem:

I needed to call wglMakeCurrent (m_hDC, m_hRC) before using the FBO, even though I'm not rendering to the screen.

DmitryM
10-09-2009, 07:08 AM
If you have a single window and don't going to use PBuffers, then you need to call wglMakeCurrent only once (right after context creation).

The main difference between FBO & PBuffers is that FBO uses current context (so, yes, it has to be activated) while PBuffer has it's own one.