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?


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(!) http://i.stack.imgur.com/Hj9Oe.jpg

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


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.


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.

  • \$\begingroup\$ Given that, what's the alternative? How can you maintain depth in your draw buffer and also acquire the depth component as a texture? \$\endgroup\$ – Rushyo Aug 23 '10 at 6:24
  • \$\begingroup\$ @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 ? \$\endgroup\$ – Calvin1602 Aug 23 '10 at 8:34
  • \$\begingroup\$ 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. \$\endgroup\$ – Rushyo Aug 23 '10 at 8:49
  • \$\begingroup\$ @Calvin1602 When I was dabbling with the renderbuffer, I found that using the depth attachment without the stencil attachment produced unwanted results. \$\endgroup\$ – Rushyo Aug 23 '10 at 9:13
  • \$\begingroup\$ @Rushyo I bet you're not setting up the texture correctly, posting code will allow us to help :) \$\endgroup\$ – Matias Valdenegro Aug 23 '10 at 11:41

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);

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.


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.

  • \$\begingroup\$ 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. \$\endgroup\$ – Rushyo Sep 2 '10 at 13:14
  • \$\begingroup\$ @Rushyo I posted an answer to this ancient question :) You might want to take a look, though you probably solved this years ago. \$\endgroup\$ – Engineer Oct 9 '12 at 22:59
  • \$\begingroup\$ @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... \$\endgroup\$ – Rushyo Apr 12 '13 at 14:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.