PDA

View Full Version : Multisample FBO and render to depth texture



eomine
05-04-2009, 08:47 PM
Hi,

I created a depth-of-field effect that works fine with a non-multisample FBO (no antialiasing). See image here:
http://www.flickr.com/photos/eomine/3498367334/

Now I'm trying to do the same effect with a multisample FBO - to get a nice antialiased image. Problem is, the depth texture is now full of (regularly distributed) black pixels:
http://www.flickr.com/photos/eomine/3498484275/

The glitch occurs in my ATI HD 4850 card (latest driver). I tested it in another PC with a Geforce 8500 and the depth texture looks fine. My HD 4850 is new (~3 months of usage) and I can play games and demos with no problems...

I'd really grateful if someone could help me with this problem.

FBO code:

// create color texture
glGenTextures( 1, &colorTexID );
glBindTexture( GL_TEXTURE_2D, colorTexID );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, APP_WIDTH, APP_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL );

// create depth texture
glGenTextures( 1, &depthTexID );
glBindTexture( GL_TEXTURE_2D, depthTexID );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY );
glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, APP_WIDTH, APP_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL );

// unbind
glBindTexture( GL_TEXTURE_2D, 0 );

// multi sampled color buffer
glGenRenderbuffersEXT(1, &colorBufID);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, colorBufID);
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFE R_EXT, 4, GL_RGBA, APP_WIDTH, APP_HEIGHT);

// multi sampled depth buffer
glGenRenderbuffersEXT(1, &depthBufID);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBufID);
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFE R_EXT, 4, GL_DEPTH_COMPONENT24, APP_WIDTH, APP_HEIGHT);

// unbind
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );

// create fbo for multi sampled content and attach buffers
glGenFramebuffersEXT(1, &mframeBufID);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mframeBufID);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, colorBufID);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthBufID);
//glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, colorTexID, 0);
//glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, depthTexID, 0);

// create final fbo and attach textures
glGenFramebuffersEXT(1, &frameBufID);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBufID);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, colorTexID, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, depthTexID, 0);

// unbind
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );


// before drawing
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, mframeBufID );
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

// ... drawing spheres here ...

// blit from multisample FBO to final FBO
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
glBindFramebufferEXT( GL_READ_FRAMEBUFFER_EXT, mframeBufID );
glBindFramebufferEXT( GL_DRAW_FRAMEBUFFER_EXT, frameBufID );
glBlitFramebufferEXT( 0, 0, APP_WIDTH, APP_HEIGHT, 0, 0, APP_WIDTH, APP_HEIGHT, GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT, GL_NEAREST );
glBindFramebufferEXT( GL_READ_FRAMEBUFFER_EXT, 0 );
glBindFramebufferEXT( GL_DRAW_FRAMEBUFFER_EXT, 0 );

martinsm
05-04-2009, 11:39 PM
Yes, I get same defect on my ATI HD2400 with GL_DEPTH_COMPONENT24 format.
Try using instead GL_DEPTH_COMPONENT32 format. It works fine with me. Also GL_DEPTH_COMPONENT32F works fine.

Stephen A
05-05-2009, 05:47 AM
There is an older thread in these forums with this issue. I can confirm it on Vista and Linux as well (4850, 9.4 drivers).

Does GL_DEPTH_COMPONENT32/32F work for you? Last time I tried this, I got a driver crash inside the FramebufferBlit call - however, I was using the core (GL 3.0) function instead of the EXT one.

eomine
05-05-2009, 06:49 AM
I replaced GL_DEPTH_COMPONENT24 with GL_DEPTH_COMPONENT32 (GL_DEPTH_COMPONENT32F was not recognized) and now I get a blank (all black) depth texture.

These are the lines I changed:

glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, APP_WIDTH, APP_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL );

glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFE R_EXT, 4, GL_DEPTH_COMPONENT32, APP_WIDTH, APP_HEIGHT);

eomine
05-05-2009, 09:57 PM
I noticed that GL_DEPTH_COMPONENT24 yields the same glitched depth texture with a non-multisample FBO too.

So it reminded me I was using GL_DEPTH_COMPONENT16 with the non-multisample version. Problem is, using 16 with multisample resulted in my application crashing on "glBlitFramebufferEXT".

If I remove the GL_DEPTH_BUFFER_BIT from the blit call, it doesn't crash but the depth texture is empty again.

* * *

FWIW, I'm using GLFW for initializing the window. I've played with the parameters in glfwOpenWindow (one of them is the number of depth bits), but it didn't seem to make a difference.

* * *

I've found this other thread (http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=255490&fpart=1) about this issue - it seems there's no solution to it?

This is really frustrating... :-(

eomine
05-07-2009, 07:29 PM
FWIW: I managed to implement my antialiased depth-of-field effect without FBOs. I used glCopyTexImage2D instead:

glEnable( GL_TEXTURE_2D );
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, colorTexID );
glCopyTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, APP_WIDTH, APP_HEIGHT, 0 );
glActiveTexture( GL_TEXTURE1 );
glBindTexture( GL_TEXTURE_2D, depthTexID );
glCopyTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 0, 0, APP_WIDTH, APP_HEIGHT, 0 );

And then I send the 2 textures to the fragment shader.

It is simpler and it runs at the same framerate of the non-multisample FBO version: ~44fps at 1280x1024px.

Some images here:
http://www.flickr.com/photos/eomine/sets/72157617756002415/