Depth Texture -> MipMap -> GLSL Shader?

I have a OpenGLSL shader which access a depth texture and then performs some calculations. However, additionally I would like to have a mipmapped version of the depth texture and this is where things go wrong.

What works…

  1. I can set up a depth texture
  2. I can access the depth texture in my shader (with mipmapping turned off).
  3. I can mipmap my depth texture (I know it works because I can use glGetTexImage() and pull the mipmapped versions off the card to main memory).

What doesn’t

  1. Once I turn on mipmapping I can no longer access it correctly in my shader.

Code snippets…

To set up the depth texture:

glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
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 );
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32_ARB , x, y, width, height, 0);

To mipmap the depth texture:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2); 
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);		
glCopyTexImage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT32_ARB , x, y, (int)baseWidth/2, (int)baseHeight/2, 0);
glCopyTexImage2D(GL_TEXTURE_2D, 2, GL_DEPTH_COMPONENT32_ARB , x, y, (int)baseWidth/4, (int)baseHeight/4, 0);
glCopyTexImage2D(GL_TEXTURE_2D, 3, GL_DEPTH_COMPONENT32_ARB , x, y, (int)baseWidth/8, (int)baseHeight/8, 0);

each pass (the mipmaps are generated automatically after this call):

glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, x,y, width, height);

quick and easy GLSL shader to test it out:

uniform sampler2D DepthImage;
vec4 fragDepth = texture2D(DepthImage, gl_TexCoord[0].st, 0.00);
if (fragDepth.r == 1.0)
   gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
else
   gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);

When I have mipmapping turned off I get green where objects are located and red everywhere else (as I should). However, once I turn on mipmapping all I get back is red everywhere (in every channel).

Anyone have any ideas?

P.S. I know I know, mipmapping a depth texture will not give me correct depth information. I don’t need the “correct” values.

I think your fragment code has a typo.

Yep it did, I have fixed it now. However that is not the problem (the typo occurred moving the code to these boards)

The code works fine up until the point I mipmap the depth texture.

Update:

When mipmapping is turned on and I move the camera very close to the object I do get green. Which would seem to indicate that it works at least on some level and that access to the base lvl texture may still be correct.

However, even when I use a large negative bias during the shader texture lookup I still see the same behaviour.

Are you sure the mipmaps are generated correctly? Try manually putting some known values into the mipmaps so you can see if it’s really the lookup that’s not working…

I know, there is not really much that you can do wrong with automatic mipmap generation, but you never know, and it might help narrow down the bug :wink:

It’s very bad practice to check equality of floating point data.

Try this instead:

if (fragDepth.r >= 0.5)

Overmind: That is a good idea and if I get time it is something I will test out.

Zeckensack: You are normally correct. However, with the non-linear nature of the depth buffer in mind, anything further that a few untis from the near clipping plane will have a depth value of around 0.95-0.99. Thus checking for > 0.5 will not be affective at all. I use the equality check because 1.0 is the clear value and should have been set exactly… if it has been modified in any fashion then I want the check to fail.

Have you tried to autogenerate mipmaps? look for sgis_generate_mipmap extension. It generates mipmap levels automatically when you render to texture.
You could then access each mipmap in GLSL with an overloaded version of texture sample function.

Thanks YengaMatic but that is what I am doing with the call…

glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);

I assume the SGI extension was promoted to core functionality and is now just GL_GENERATE_MIPMAP.