Saturday, November 7, 2009

Revisiting Shadows Methods

shadows are always been an issue when it comes to real-time app, there is no such thing a perfect method for shadows, until now i choose vsm for shadowing, but the more i work with them, the more i get the feeling its great for "demos" not for complex scene where shadow complexity is high , yes i know about the bleeding issues and how to minimize them, but there are scenes where you need to minimize them a lot and at the end you just get simple shadow map, and the softness you applied by blurring or such isn't noticed so much.
because of this i started to investigate few other methods, and i must say i got really good results:
a word about poplar shadowing methods:
1. sm - old school shadow maps
2. pcss - percentage closer soft shadows
3. vsm - variance shadow maps
4. esm - exponential shadow maps
5. cssm - cascaded shadow maps
6. pssm - parallel split shadow maps
as much as it will sound odd, i choose method 1 for indoor shadows, yes, old school shadow maps with poission disk and jittering gives me very good results.
while method 2 sound really good, its not applied very well for every scene, it also not free in terms of performance.
anyway, i created 16 samples of poission disk and generated jitter texture which i passed to the shader. the poission disk can be tuned for more samples or less, the jittering can be tuned for more jitter or less.
because i use two shadow maps, static for static shadows and dynamic for dynamic shadows, i managed to optimize this by using one texture with offsetting.
method 5,6 used for outdoor scenes, i use pssm...
here is few screenshots:

complex shadows from 2 light sources
note that vsm will fail below the platform (light bleeding) and the fence details won't be visible even with 1k shadow maps because the compassion is based on probability and could be failed where simple compassion will pass.

complex surface casting shadows

zoom in on shadows

before you said its not so impressive, note that the 2 light sources using only 8 samples on 1k maps, the barrel is dynamic object which means the dynamic shadow map is updated and merged with static shadow maps, the fence have very tiny elements, and it all runs on my old g6600, so i think its pretty good ;)


Juan said...

Hi when you say you use two shadow maps one for dynamic and one for static shaders. Does that mean that you pass in two shadow maps into your shader? I do not understand what you mean when you say you used one texture for both with offseting. For example for a point light you would need a cube map, how would you use two seperate textures for dynamic and staic objects in this case?

orenk2k said...

hi juan
1. for proj lights you can simply use 2*Width X height and offset it in shader when you want to sample dynamic/static part.
you only need to bind one texture.
but you need to samples!

2. for point lights its a little bit harder, you have few optons:
1. use two textures for point lights, you have few in a scene anyway.
2. unwrap cube map into 2d texture and use whatever method you like as you did for proj lights.

a better method is to use one channel for static shadows and another for dynamic shadows, this way you only set one texture and sample once, this could be used to optimize both type of lights.

hope this clears few things...

Juan said...

Hi thanks for your quick reply, I like your very last response of storing both the dynamic and static shadow maps in different channels of the same texture. With this you get the best of both worlds. Thanks!