# FBO Depth Buffer not working

I'm trying to get the depth buffer for my 2D game working by offsetting the z value of the rectangles. For some reason, my depth buffer is coming back empty. The value is always 0. I'm assuiming there is something wrong with how I attach the depth buffer to the FBO? But I've looked over that code many times and don't see anything wrong with it. Let me know if you need more information.

• I have depth testing enabled with GL_LEQUAL.
• I have znear and zfar set to 1.f, -10.f and I have 9 quads setup at three different depths.
• I have set glClearDepth(1.0) and I clear bot the COLOR_BUFFER_BIT and DEPTH_BUFFER_BIT before I draw to the FBO, however the value is still 0.

FBO setup:

RenderTarget::RenderTarget(int width, int height) {

mWidth = width;
mHeight = height;
mVbo = 0;

// Create the color buffer
glGenTextures(1, &mTextureId);
glBindTexture(GL_TEXTURE_2D, mTextureId);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

// Create the depth buffer
glGenTextures(1, &mDepth);
glBindTexture(GL_TEXTURE_2D, mDepth);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, mWidth, mHeight, 0, GL_RED, GL_BYTE, NULL);

/*glGenRenderbuffers(1, &mDepth);
glBindRenderbuffer(GL_RENDERBUFFER, mDepth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32, mWidth, mHeight);*/

// Create the frame buffer
glGenFramebuffers(1, &mFbo);
glBindFramebuffer(GL_FRAMEBUFFER, mFbo);

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextureId, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, mDepth, 0);

GLenum err = glCheckFramebufferStatus(GL_FRAMEBUFFER);
assert(err == GL_FRAMEBUFFER_COMPLETE);

glBindFramebuffer(GL_FRAMEBUFFER, 0);

createVbo();
}


#version 120

uniform sampler2D diffuseMap;
uniform sampler2D lightmap;
uniform sampler2D depthMap;

varying vec4 texCoord[2];

void main()
{
vec4 color = texture2D(diffuseMap, gl_TexCoord[0].st);
vec4 light = texture2D(lightmap, gl_TexCoord[0].st);
vec4 depth = texture2D(depthMap, gl_TexCoord[0].st);

vec4 final = color * vec4(0.1);
final += color * light;
gl_FragColor= vec4(depth.r, depth.r, depth.r, 1.0);
}


Method to draw sprites to the screen/framebuffer

void GraphicsDevice::drawSprite(ISprite *sprite, float x, float y, float z, Material::TextureType type, Color c) {

glActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glBindBuffer(GL_ARRAY_BUFFER, sprite->getVbo());

glBindTexture(GL_TEXTURE_2D, sprite->getMaterial()->getTexture(type)->getId());

glPushMatrix();
glTranslatef(x, y, z);
glColor4f(c.r, c.g, c.b, c.a);

glVertexPointer(3, GL_FLOAT, sizeof(Vertex), (void*)offsetof(Vertex, x));
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), (void*)offsetof(Vertex, tx));

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

glPopMatrix();

glBindBuffer(GL_ARRAY_BUFFER, 0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);

}

• Maybe your videocard doesn't suppot GL_DEPTH_COMPONENT32? Try only GL_DEPTH_COMPONENT to allow the card to choose. – kaoD Feb 16 '12 at 15:42

The problem was I was creating and binding the depth buffer texture to GL_DEPTH_ATTACHMENT. I found some random code that attached the depth buffer to GL_DEPTH_STENCIL_ATTACHMENT, so I tried that out and it works exactly as I expect it to. So the new FBO code looks like this

glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, mWidth, mHeight, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, mDepth, 0);


I would really appreciate it if someone could explain why this works and my previous one doesn't.

I needed depth buffer to my application as well and indeed this:

glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, mWidth, mHeight, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, mDepth, 0);


worked but sadly GL_DEPTH_COMPONENT32 and GL_DEPTH_COMPONENT failed as well.

So i've read the documentation for glTexImage2D and i found the following on the error section:

GL_INVALID_OPERATION is generated if format is GL_DEPTH_COMPONENT and internalFormat is not GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24, or GL_DEPTH_COMPONENT32F.

GL_INVALID_OPERATION is generated if internalFormat is GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24, or GL_DEPTH_COMPONENT32F, and format is not GL_DEPTH_COMPONENT.


So in the case above if you change ..GL_RED.. to ..GL_DEPTH_COMPONENT.. it should work, it worked for me. All in all, internalFormat and format should be GL_DEPTH_COMPONENT, otherwise you'll get GL_INVALID_OPERATION.

Did you miss glEnable(GL_DEPTH_TEST)? I don't see it anywhere in your code (although I'm aware you didn't post it all, it might be somewhere else.)

Also, both zNear and zFar MUST BE positive in perspective projection (not sure about orthogonal.) Actually, it doesn't make sense (at least syntactically) to have the planes reversed. Bear in mind that even if OpenGL looks towards the negative Z axis, z-planes are positioned relative to the viewpoint (positive being forwards from it.)

I'd be glad if someone posted a use case where negative planes are useful, and even more glad if it made sense to have the planes reversed (zFar being behind the viewer as you do.)

• I do have depth test enabled. The reason why I used negative planes is simply so my Z values don't have to be negative when I translate the rectangles. I changed the near/far range to be positive, but that didn't fix anything. I added a new point to my OP: I have glClearDepth(1.0) and I clear the depth buffer before drawing to the FBO, but the values are all still 0. – Ryan Capote Feb 16 '12 at 15:32
• To avoid negative Z values you just have to set the Z scale to -1.0 (effectively reversing the Z viewing direction and making you "look" backwards.) Added some comments to your question which may help too. – kaoD Feb 16 '12 at 15:40
• @rcapote: Are you using a perspective projection or an orthographic one? – Nicol Bolas Feb 16 '12 at 20:09
• @NicolBolas Ortho – Ryan Capote Feb 16 '12 at 22:49