So after geting a bit annoyed with constantly tweaking the current shadowing setup in an attempt to get better filtering I've decided to give exponential variance shadow mapping (EVSM) another try. This was the technique I using previously for quite some time, but There are some issues with this shadowing approach but 90% of the time they are pretty decent.
AdvantagesPerformance is better than the current setup, but not by as much as I was hoping. There are reasons for this such as having to render directional lighting and ambient lighting independently as I need to fit 4 shadow maps within the 8 texture limit, the shadows also receive a post gaussian blur. My frame rate is now around 340-400fps with EVSM whereas with the existing shadowing I'm getting 280-350fps, so around a 50 frame improvement which is not bad. I think the biggest gain will be with point or spot lights that are shadow casting and overlap each other. With the existing approach an overlapping point and spot light will esaly cause my frame rate to drop to below 200 thanks to the oversampling of shadowmaps (this is a big problem and ultimately can result in inconsistent frame rate), where as with EVSM only requires a single lookup.
Filtering is also an big advantage thanks to shadow maps keeping a linear min/mag filter, as a result the shdowmaps also have far less aliasing/shimmering artifacts which is typically noticeable with the existing approach. Shadows are blurred using a 7x7 weighted gaussian blur.
DisadvantagesVariance shadow mapping on it own is a prettey useless technique thanks to shadow with high depth complexity can cause penumbra to prodce a leek resuling light bleeding. Applying an exponential wrap to shadows depth helps to greatly reduces bleeding artifacts but they will occur when shadows overlap at the base of casters. Another big issue is that small shadow casters can be lost during the blur pass as brighter pixel will always overwrite darker neighboring pixel.
Another problem is every object has the ability to receive a shadow so all objects have to be drawn to the depth map, which means we cannot pick and choose whether an object should act as a caster or not. This is cause of a concern when it comes to draw call optimization as more objects will need to be drawn than are necessary. I will have to implement shadow caching for static lights (this something I had to do previously when using EVSM), that will capture static objects into its own depth map then when it come to updating we only have to draw dynamic objects that are moving within the bound of the lights shadowmap.
Memory is probably the biggest issue, for directional light I'm useing three 1024² 32bit (r16g16) depth textures used for static and dynamic rendering and six 1024² 64bit (a16r16g16b16) textures used for combining dynamic/static and gaussian blur. Thats approximately 60mb which is more than the gbuffer which is approximately 59mb at 1440p, And thats just for the directional light. When I start working on local point/spot lights, shadowing going to consume even more vram and in dx9/32bit apps there is a set limit. This is definitely a concern and will most likely result in removing the current virtual texture terrain system that consumes a ridiculous 216megs and go back a more simpler less memory consuming but potentially slower approch.
Here's a video capture I did earlier, errors are quite hard to see but are still there.
https://www.youtube.com/watch?v=lXFdYuMjOnAScreenshot of trees sample.