# Getting a texture from a renderbuffer in OpenGL?

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(!) 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.

• 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 6: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 8: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 8: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 9:13
• @Rushyo I bet you're not setting up the texture correctly, posting code will allow us to help :) – 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);
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);

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.