14

I've got a renderbuffer (DepthStencil) in an FBO and I need to get a texture from it. I can't have both a DepthComponent texture and a DepthStencil renderbuffer in the FBO, it seems, so I need some way to convert the renderbuffer to a DepthComponent texture after I'm done with it for use later down the pipeline.

I've tried plenty of techniques to grab the depth component from the renderbuffer for weeks but I always come out with junk. All I want at the end is the same texture I'd get from an FBO if I wasn't using a renderbuffer. Can anyone post some comprehensive instructions or code that covers this seemingly simple operation?

EDIT:

Linky to an extract version of the code http://dl.dropbox.com/u/9279501/fbo.cs

Screeny of the Depth of Field effect + FBO - without depth(!) https://i.stack.imgur.com/Hj9Oe.jpg

Screeny without Depth of Field effect + FBO - depth working fine https://i.stack.imgur.com/boOm1.jpg

Rushyo
  • 1,103
  • 9
  • 18

4 Answers4

2

Alternately, you can just blit from one FBO to another, such as from a renderbuffer-based one to a texture-based one. I do it this way:

glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_renderBufferSurface->m_fbo);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_textureSurface->m_fbo);
glBlitFramebufferEXT(0, 0, m_renderBufferSurface->m_width, m_renderBufferSurface->m_height, 0, 0, m_textureSurface->m_width, m_textureSurface->m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST);

(In your case, where you want to depth buffer, you can use GL_DEPTH_BUFFER_BIT instead of GL_COLOR_BUFFER_BIT)

After blitting into the texture-based renderbuffer, you can then use the texture as normal; passing it into shaders as a uniform or whatever you like.

Trevor Powell
  • 21,382
  • 1
  • 59
  • 94
1

No, that's not possible. At most you can glReadPixels the data to the CPU, and create a texture of it, but that will be cumbersome and slow. Renderbuffers aren't meant for it, that functionality is only provided by textures.

Dr. Snoopy
  • 5,105
  • 10
  • 33
  • 36
  • Given that, what's the alternative? How can you maintain depth in your draw buffer and also acquire the depth component as a texture? – Rushyo Aug 23 '10 at 06:24
  • @Rushyo : An alternative could be to get rid of the stencil buffer (if possible!) and make the depth renderbuffer a depth texture. Why are you using a stencil ? – Calvin1602 Aug 23 '10 at 08:34
  • Essentially whenever I acquire the depth texture, my depth tests break. If I attach a depth attachment to my FBO, the FBO doesn't write any depth information elsewhere - so when I try to retrieve the color attachment there's no depth testing on it (which their normally is if I don't have a depth attachment). I've tried every combination I can think of, including the aforementioned 'cumbersome and slow' method. Whatever I do I can't get both a 'typical' render of my scene in one texture and just the depth in another. – Rushyo Aug 23 '10 at 08:49
  • @Calvin1602 When I was dabbling with the renderbuffer, I found that using the depth attachment without the stencil attachment produced unwanted results. – Rushyo Aug 23 '10 at 09:13
  • @Rushyo I bet you're not setting up the texture correctly, posting code will allow us to help :) – Dr. Snoopy Aug 23 '10 at 11:41
  • @Rushyo : IMHO you should begin by this problem. What hardware do you get ? How do you setup your FBO ? – Calvin1602 Aug 23 '10 at 11:46
  • I'll post a full code dump tonight when I've got access to my workstation. It's C#/OpenTK. It's seen many many iterations, so I'll just post the latest. Appreciate the assistance! – Rushyo Aug 23 '10 at 12:30
  • Posted up as of last night. – Rushyo Aug 24 '10 at 09:53
  • @Rushyo I don't see if you are using glCheckFramebufferStatus, are you? – Dr. Snoopy Aug 24 '10 at 15:20
  • I am. Just stripped out error checking from that snippet. I also do generic error-checking after every meaningful action. – Rushyo Aug 24 '10 at 17:45
1

What you are asking is possible in OpenGL 3.2. I've got my FBO spitting out diffuse colour to a colour texture, normals to another colour texture, and depth to a depth texture -- no renderbuffers needed. In fact renderbuffers are just a problem, because you cannot sample from them, so you'd have to use glReadPixels(...) or otherwise somehow copy the data out of the RBO and into a texture on the CPU, instead of just maintaining everything in GPU memory. So...

If you really want to, you can write code in your first-pass shader to manually output stuff like depth, to a separate colour texture attachment in your FBO. That would be for use by you in your post-pass shaders. For OpenGL's use in its internal depth-testing, you would additionally need either an RBO or texture set as your FBO's GL_DEPTH_ATTACHMENT. But you can set up a single texture to serve both -- this is more efficient & easier to use.

My depth texture setup code looks like this (Java, just ignore the ByteBuffer stuff... and note I use "id" to refer to integer handles/pointers, since that concept doesn't really sit well in Java):

        gBufferDepthTexture = new Texture();
        gBufferDepthTexture.id = glGenTextures();
        gBufferDepthTexture.unit = 2;
        gBufferDepthTexture.width = Display.getWidth();
        gBufferDepthTexture.height = Display.getHeight();
        gBufferDepthTexture.bytes = ByteBuffer.allocateDirect(Display.getWidth()*Display.getHeight() * 4);
        glActiveTexture(gBufferDepthTexture.unit + GL_TEXTURE0); //eg. 0 + 33984 = GL_TEXTURE0, while 31 + 33984 = GL_TEXTURE31.
        glBindTexture(GL_TEXTURE_2D, gBufferDepthTexture.id);

        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, gBufferDepthTexture.width, gBufferDepthTexture.height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, gBufferDepthTexture.bytes);
        //...GL_UNSIGNED_INT or GL_UNSIGNED_BYTE may work better for you, instead... YMMV.

        //glPixelStorei(GL_PACK_ALIGNMENT, 4);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

And later:

        glBindFrameBuffer(GL_DRAW_FRAMEBUFFER, fbo.id);
        //your existing glFramebufferTexture2D(...) calls here
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, gBufferDepthTexture.id, 0);

You can now pass gBufferDepthTexture (or what have you) as a uniform to your second, third pass fragment shaders. I think we can safely assume that you can do exactly the same thing with the stencil buffer.

Engineer
  • 29,455
  • 4
  • 72
  • 120
0

You should be able to create a texture (instead of a RenderBuffer) using the GL_DEPTH_STENCIL format. I'm not sure of the exact process for using depth from such a texture in a shader program (which I assume you're using, since you're using FBOs), but the OpenGL spec should specify which color channels get which values (my guess would be that R,G, and B all get set to depth and A gets set to stencil).

I target OpenGL 3.2 these days, so you may need to verify that texture format is workable for you. I can never remember which versions introduce different features.

Branan
  • 211
  • 2
  • 6
  • The trouble then isn't capturing the GL_DEPTH_STENCIL component in a texture, but the fact that all depth information is lost in the FBO whenever you do so. The FBO becomes useless for then rendering the scene to the draw buffer. Hence I was using a Renderbuffer in the hopes of bypassing this issue. I think for now I have no option but to make two passes to grab the depth + draw information separately =( expensive-as-hell until I can find a way around it. – Rushyo Sep 02 '10 at 13:14
  • @Rushyo I posted an answer to this ancient question :) You might want to take a look, though you probably solved this years ago. – Engineer Oct 09 '12 at 22:59
  • @NickWiggill I wish! Fudged something and moved on with my life. Can't actually test your answer until I recreate the assets that I used in this prototype. Might get around to that at some point... – Rushyo Apr 12 '13 at 14:07