Sign in to follow this  
Yours3!f

reusing depth stencil texture in another fbo

Recommended Posts

Hi,

I'm rendering to a depth stencil texture using a fbo and a rbo. After the rendering is done, I want to use the depth stencil texture in another fbo. I tried attaching the same rbo to the other fbo, and also attaching the texture as a depth stencil attachment to the other fbo, but it didn't work.

So how do I do that? (if its possible)

Here's the code that would render some texture onto the screen where I didn't put 1 into the stencil buffer
[CODE]
//Set up FBO with which I render to the depth and stencil textures
fbo.create();
fbo.bind();

depth_stencil.create();
depth_stencil.valid = true;

depth_stencil.bind();
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_DEPTH24_STENCIL8, ( GLsizei )w, ( GLsizei )h, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0 ); //depth + stencil
depth_stencil.width = w;
depth_stencil.height = h;

rbo.create();
rbo.bind();
rbo.set_storage_format( GL_DEPTH24_STENCIL8, w, h );
rbo.width = w;
rbo.height = h;

rbo.attach_to_frame_buffer( GL_DEPTH_STENCIL_ATTACHMENT, &fbo );
depth_stencil.attach_to_frame_buffer( GL_DEPTH_STENCIL_ATTACHMENT, &fbo );

fbo.check();
fbo.unbind();

//set up another fbo
another_fbo.create();
another_fbo.bind();

GLenum modes[] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers( 1, modes );

another_tex.create(); //create a texture to render to
another_tex.valid = true;

another_tex.bind();
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_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, ( GLsizei )w, ( GLsizei )h, 0, GL_RGBA, GL_FLOAT, 0 );
another_tex.width = w;
another_tex.height = h;

another_tex.attach_to_frame_buffer( GL_COLOR_ATTACHMENT0, &another_fbo );

depth_stencil.attach_to_frame_buffer( GL_DEPTH_STENCIL_ATTACHMENT, &another_fbo );
rbo.attach_to_frame_buffer( GL_DEPTH_STENCIL_ATTACHMENT, &another_fbo );

another_fbo.check();
another_fbo.unbind();

//bind and clear fbo (color depth stencil)
[...]

//render objects placing 1 to the stencil buffer
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);

render();

//bind and clear another fbo (only clear color)
[...]

//render full-screen quad with some texture where we didnt render anything
glStencilFunc(GL_NOTEQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

some_texture.bind();
render_quad();

//unbind another fbo
[...]

//show our work
glDisable(GL_STENCIL_TEST);
another_tex.bind();
render_quad();

[/CODE]

Share this post


Link to post
Share on other sites
What is the problem exactly? If the fbo check isn't working, then you should say what the error message is. If nothing renders to it, then you probably left some gl state on or off and it is causing you trouble. Can you render the same thing to the back buffer?

Share this post


Link to post
Share on other sites
[quote name='Yours3!f' timestamp='1335292777' post='4934508']
rbo.attach_to_frame_buffer( GL_DEPTH_STENCIL_ATTACHMENT, &fbo );
depth_stencil.attach_to_frame_buffer( GL_DEPTH_STENCIL_ATTACHMENT, &fbo );
[/quote]
Why are you binding a RBO and a texture to a single FBO at the same attachment point ? I would think, that only the last, in your case depth_stencil, will be taken.

[quote name='Yours3!f' timestamp='1335292777' post='4934508']
depth_stencil.attach_to_frame_buffer( GL_DEPTH_STENCIL_ATTACHMENT, &another_fbo );
rbo.attach_to_frame_buffer( GL_DEPTH_STENCIL_ATTACHMENT, &another_fbo );
[/quote]
The same here, this time the RBO is the last one, and therefore the first depth_stencil will not be taken.

Share this post


Link to post
Share on other sites
[quote name='V-man' timestamp='1335354788' post='4934710']
What is the problem exactly? If the fbo check isn't working, then you should say what the error message is. If nothing renders to it, then you probably left some gl state on or off and it is causing you trouble. Can you render the same thing to the back buffer?
[/quote]

well, let me try to explain what I'm trying to accomplish:
1. render scene geometry with stencil test enabled, and put 1 to the stencil buffer where I draw
2. render the background texture (skybox) where the stencil buffer is 0
3. blur scene where needed (where the stencil buffer is 1)

now in step 1 and 2 I render to FBO #1 that has a D24S8 attached to it.
in step 3 I do a gaussian blur that I render to a texture via FBO #2 ("another fbo") which goes like this:
blur the scene where the stencil buffer is 1 (the geometry) using the D24S8 buffer from FBO #1

my problem is that I don't know how can I attach the D24S8 texture from FBO #1 to FBO #2 and still do stencil testing.
I assumed that I had to attach the same buffers, but that doesn't seem to work.


[quote name='Ashaman73' timestamp='1335360091' post='4934740']
[quote name='Yours3!f' timestamp='1335292777' post='4934508']
rbo.attach_to_frame_buffer( GL_DEPTH_STENCIL_ATTACHMENT, &fbo );
depth_stencil.attach_to_frame_buffer( GL_DEPTH_STENCIL_ATTACHMENT, &fbo );
[/quote]
Why are you binding a RBO and a texture to a single FBO at the same attachment point ? I would think, that only the last, in your case depth_stencil, will be taken.

[quote name='Yours3!f' timestamp='1335292777' post='4934508']
depth_stencil.attach_to_frame_buffer( GL_DEPTH_STENCIL_ATTACHMENT, &another_fbo );
rbo.attach_to_frame_buffer( GL_DEPTH_STENCIL_ATTACHMENT, &another_fbo );
[/quote]
The same here, this time the RBO is the last one, and therefore the first depth_stencil will not be taken.
[/quote]
[quote name='Ashaman73' timestamp='1335360091' post='4934740']
[quote name='Yours3!f' timestamp='1335292777' post='4934508']
rbo.attach_to_frame_buffer( GL_DEPTH_STENCIL_ATTACHMENT, &fbo );
depth_stencil.attach_to_frame_buffer( GL_DEPTH_STENCIL_ATTACHMENT, &fbo );
[/quote]
Why are you binding a RBO and a texture to a single FBO at the same attachment point ? I would think, that only the last, in your case depth_stencil, will be taken.

[quote name='Yours3!f' timestamp='1335292777' post='4934508']
depth_stencil.attach_to_frame_buffer( GL_DEPTH_STENCIL_ATTACHMENT, &another_fbo );
rbo.attach_to_frame_buffer( GL_DEPTH_STENCIL_ATTACHMENT, &another_fbo );
[/quote]
The same here, this time the RBO is the last one, and therefore the first depth_stencil will not be taken.
[/quote]

umm so that the FBO actually does depth testing and stencil testing, but uses the texture attached to perform the tests. Am I doing that correctly?

Share this post


Link to post
Share on other sites
[quote name='Yours3!f' timestamp='1335368262' post='4934783']
umm so that the FBO actually does depth testing and stencil testing, but uses the texture attached to perform the tests. Am I doing that correctly?
[/quote]
Try top attach either the rbo or the texture, but not both.

Share this post


Link to post
Share on other sites
[quote name='Ashaman73' timestamp='1335417465' post='4934967']
[quote name='Yours3!f' timestamp='1335368262' post='4934783']
umm so that the FBO actually does depth testing and stencil testing, but uses the texture attached to perform the tests. Am I doing that correctly?
[/quote]
Try top attach either the rbo or the texture, but not both.
[/quote]

Thank you, attaching the rbo only did it. But I have another issue, I render the blurring at half resolution, so I resize the viewport to half the screen size, and back when I'm done. When blurring I can see that it only uses the lower left quater of the stencil buffer because of the half resolution. Now how can I resize the stencil buffer as well, so that it masks the rendering correctly? Is there a "usual" way?

Share this post


Link to post
Share on other sites
if you want to use the stencil results from a framebuffer, you need to create it as a texture, and attach it to the fbo as a texture, than later, when using the values in another part of the rendering, you simply bind the texture before you draw, and then in the shader do whatever you want with the result.

Share this post


Link to post
Share on other sites
[quote name='slicer4ever' timestamp='1335559008' post='4935471']
if you want to use the stencil results from a framebuffer, you need to create it as a texture, and attach it to the fbo as a texture, than later, when using the values in another part of the rendering, you simply bind the texture before you draw, and then in the shader do whatever you want with the result.
[/quote]

I thought about that as well, and that would solve the problem, but isn't the fixed pipeline stencil testing faster?

Share this post


Link to post
Share on other sites
hmm, i re-read your original problem, and i misunderstood when i originally posted. while doing a shader-tex attachment is a possible option, what you doing is much more efficient, yes.

in short, you were already on the right track, and i carelessly posted, my apologies.

Share this post


Link to post
Share on other sites
[quote name='slicer4ever' timestamp='1335605236' post='4935550']
hmm, i re-read your original problem, and i misunderstood when i originally posted. while doing a shader-tex attachment is a possible option, what you doing is much more efficient, yes.

in short, you were already on the right track, and i carelessly posted, my apologies.
[/quote]

well, no problem :)

I actually tried to mask the blurring using the shader based approach, but while rgb contained depth, a contained pure white, meaning all pixels passed the stencil test...
But that is impossible, since the background texture (which gets rendered to where stencil == 0) renders correctly.

I also thought about generating the 2nd level mipmap of the depth-stencil texture (thus generating a half-res texture) and use that for stencil testing, but how could that be done?

Share this post


Link to post
Share on other sites
if you want the skybox drawn only on pixel in wich it was not drawn you don't need FBO. you can achieve that with early z culling. You have just to draw skybox as last drawcall, just have to keep proper Z test to make z culling work ;-)

Share this post


Link to post
Share on other sites
[quote name='DemonRad' timestamp='1335680706' post='4935769']
if you want the skybox drawn only on pixel in wich it was not drawn you don't need FBO. you can achieve that with early z culling. You have just to draw skybox as last drawcall, just have to keep proper Z test to make z culling work ;-)
[/quote]

well the skybox already works, the point is that I need to blur the scene later, and I'd like to save some texture fetches by masking out the skybox.

Share this post


Link to post
Share on other sites
[quote name='Yours3!f' timestamp='1335684549' post='4935774']
well the skybox already works, the point is that I need to blur the scene later, and I'd like to save some texture fetches by masking out the skybox.
[/quote]
Here might be a conceptual issue. When you blur, you most likely use a two pass or a single pass approach. When using a two pass approach(x/y axis), utilizing the stencil buffer could result in interesting effects (you stencil out the target and not the source texels). When using a single pass approach, you have a similar effect and you would have a performance impact (single pass (n*n) vs two pass (2*n) ).

Why not use the alpha channel (or some other) to determine a mask by discarding a pixel once the alpha channel has a value less than X. This is not as fast as a stencil buffer, but it should work on a block base, that is, when all pixels in a certain block (i.e. 16x16 pixel block) are discarded , then it is faster for this block. When using large parts of the image as background, this should performe better than the brute force approach. This way you could even implement a [url="http://en.wikipedia.org/wiki/Bilateral_filter"]bilateral [/url]gauss filter (ignore masked source texels).

And try to utilise linear texture blending to half the number of taps needed for the blurring.

Share this post


Link to post
Share on other sites
[quote name='Ashaman73' timestamp='1335765965' post='4935998']
[quote name='Yours3!f' timestamp='1335684549' post='4935774']
well the skybox already works, the point is that I need to blur the scene later, and I'd like to save some texture fetches by masking out the skybox.
[/quote]
Here might be a conceptual issue. When you blur, you most likely use a two pass or a single pass approach. When using a two pass approach(x/y axis), utilizing the stencil buffer could result in interesting effects (you stencil out the target and not the source texels). When using a single pass approach, you have a similar effect and you would have a performance impact (single pass (n*n) vs two pass (2*n) ).

Why not use the alpha channel (or some other) to determine a mask by discarding a pixel once the alpha channel has a value less than X. This is not as fast as a stencil buffer, but it should work on a block base, that is, when all pixels in a certain block (i.e. 16x16 pixel block) are discarded , then it is faster for this block. When using large parts of the image as background, this should performe better than the brute force approach. This way you could even implement a [url="http://en.wikipedia.org/wiki/Bilateral_filter"]bilateral[/url]gauss filter (ignore masked source texels).

And try to utilise linear texture blending to half the number of taps needed for the blurring.
[/quote]

Well, I use a separated gausssian blur with linear sampling ([url="http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/"]http://rastergrid.co...inear-sampling/[/url]), and I check the normals, so that the blur is geometry aware. I also implemented masking by checking if the normal vector is a null vector (only checking the source), and this seems to do the trick, but I was seeking for a faster method. So this is kind of the alpha-channel method that you described. But if stencil testing is only needed on the source as you described, than I guess the problem is solved [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]

Thanks for the bilateral approach I'll look into that. Edited by Yours3!f

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this