Mipmap errors on a Variance shadow map

I have written a program for the realtime data visualization of molecular dynamics simulations. In it, I tried to use variance shadow mapping to help provide depth cues to the user.

When I use my variance shadow map (GL_LINEAR), it looks great if a little blocky (can’t antialias my deferred render yet).

But if I switch to GL_LINEAR_MIPMAP_LINEAR filtering on the shadow map data I get the following result with bright pixels on the sphere edges.

My question is, does something unexpected happen when using mipmapping on 32 bit textures on Nvidia hardware? Is it converted to 8bit or something? Can I switch formats to fix this? I’m not sure what’s actually causing the errors on the edges, but it appears to occur in square 4x4 blocks when mipmapping so it’s definitely the interpolation that’s messing it up.

Thanks in advance for any feedback or ideas that you might have.


The shadow depth and depth^2 data is stored in a GL_RG32F texture. I create it using this instancing variance shader
and I light the scene using this deferred lighting shader

I haven’t checked if this mipmapping “error” occurs on other hardware apart from Nvidia (quadro 4000) as I haven’t got access to any at the moment.

Reminds me of this:

Ah exactly right! Thanks for the pointer Dark Photon, you’re a legend. I like the Dark Helmet avatar too, I loved spaceballs as a kid.

Just some notes for others who come after me.

I didn’t see this problem before with a forward rendering setup. This is because the mipmap calculation must only be performed with a set of fragments drawn recently. When rendering the spheres, only fragments from a single sphere would be active in the texture lookup calculations and would not cause an extremely low LOD mipmap to be accessed as these fragments are close together in the shadow map.

When I switched to deferred shading, I moved the shadow map lookups into a full screen pass, and now my active fragments can come from any objects, causing large gradients in the shadow map coordinates and thus causing the texture lookup to select a low LOD mipmap.

I can’t see a way of fixing this, apart from just disabling mipmaps on the shadow map texture.

Thanks again!

You know another option just occurred to me. You’re probably rasterizing a normal in the G-buffer. Maybe you could do something with dotting that with the light space Z axis. Closer to 1, use highest res MIP; closer to 0, use the lowest res MIP. Not perfect, but gives you something physically based.

Sure thing!

I like the Dark Helmet avatar too, I loved spaceballs as a kid.

Same here. I laughed so hard in that movie the first time I could hardly breath. I need to watch that again :slight_smile:

Some more notes on this problem.
Found this in the GLSL 330 spec, pg 102
“[Derivative] Functions should be evaluated within the interior of a primitive.”
which confirms why shadow-map mipmapping is fine for forward rendering (primitives for each object during light calcs) and not for deferred shading (one full-screen primitive during light calcs).

The dotting is a great idea as I do have the normals in the G-buffer. I’ll try and work my way through section 3.8.11 to figure out a mapping for the dot to lod parameter of textureLod, as I’m not currently sure of its range.

Thanks again!

Humus did a demo on a way to avoid the mip mapping issue when doing screen space effects:

Just to close this thread. In the end I gave up on mipmapping the shadow maps as I incur a significant performance penalty just turning it on, without even fixing the issue.

One method to fix the issue is described by the link in the previous post. You sample the depth around the current pixel (easy if you’re doing deferred shading) and at a discontinuity the changes in the depths in the left-right or top-bottom directions will be significantly different. Use this as a condition to clamp to mipmap 0.

But as I said, generating the mipmaps and mipmapping appears to slow my render down by a factor of 2x on HD6770, quadro 4000 and 480M so I avoid mipmapping the shadow map altogether.