Jump to content

Variance Shadow Maps


Josh

6,010 views

 Share

After a couple days of work I got point light shadows working in the new clustered forward renderer. This time around I wanted to see if I could get a more natural look for shadow edges, as well as reduve or eliminate shadow acne. Shadow acne is an effect that occurs when the resolution of the shadow map is too low, and incorrect depth comparisons start being made with the lit pixels: By default, any shadow mapping alogirthm will look like this, because not every pixel onscreen has an exact match in the shadow map when the depth comparison is made:

9R3Ek.png.52512f6d5379359d4206710ecec65aa1.png

We can add an offset to the shadow depth value to eliminate this artifact:

eTKDx.png.76e1699be2c256cbcca465ffc27095e4.png\

However, this can push the shadow back too far, and it's hard to come up with values that cover all cases. This is especially problematic with point lights that are placed very close to a wall. This is why the editor allows you to adjust the light range of each light, on an individual basis.

I came across a techniqe called variance shadow mapping. I've seen this paper years ago, but never took the time to implement it because it just wasn't a big priority. This works by writing the depth and depth squared values into a GL_RG texture (I use 32-bit floating points). The resulting image is then blurred and the variance of the values can be calculated from the average squared depth stored in the green channel.

f162equ01.jpg.29d980b8ca60ed770875c0dec1a9cdb8.jpg

f162equ02.jpg.55f072b9c23296075bc6fc6e0e3c4698.jpg

Then we use Chebyshev's inequality to get an average shadow value:

f162equ03.jpg.52f24082b2fd6c669da2aab16663e35a.jpg

So it turns out, statistics is actually good for something useful after all. Here are the results:

Image4.thumb.jpg.fd8733661be4877478f15c375e1a13d1.jpg

The shadow edges are actually soft, without any graininess or pixelation. There is a black border on the edge of the cubemap faces, but I think this is caused by my calculated cubemap face not matching the one the hardware uses to perform the texture lookup, so I think it can be fixed.

As an added bonus, this eliminates the need for a shadow offset. Shadow acne is completely gone, even in the scene below with a light that is extremely close to the floor.

Image3.thumb.jpg.878272762985faf2ee8c832a94eb3bdb.jpg

The banding you are seeing is added in the JPEG compression and it not visible in the original render.

Finally, because the texture filtering is so smooth, shadowmaps look much higher resolution than with PCF filtering. By increasing the light range, I can light the entire scene, and it looks great just using a 1024x1024 cube shadow map.

Image1.thumb.jpg.6e29c2fa204405f1fec529a5a3c04e9d.jpg

VSMs are also quite fast because they only require a single texture lookup in the final pass. So we get better image quality, and probably slightly faster speed. Taking extra time to pay attention to small details like this is going to make your games look great soon!

  • Like 1
  • Upvote 3
 Share

0 Comments


Recommended Comments

There are no comments to display.

Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...