torstai 5. huhtikuuta 2012

Soft realtime shadows for gles2.0.

Couple months ago I decided to master shadow techniques for mobile environment, I didn't know at the time would take that much effort. After some serious reading and googling I noticed that there are nothing on interwebs how to do it at least at mobile but that didn't discouraged me.

Shadow mapping seems to be only viable technique for general case.(don't forget that Blinn shadows can do miracles in some special cases). But normal shadow mapping algorithm need really big textures to get enough precision to look good and only give hard edges. But even normal shadow mapping is bit pain for gles2.0 because depth texture is not part of standard but an extension which penetration is not that good.
Also there are no floating points textures. This problem is easily solve by packing depth value which is float  to int bits by hand and outputting values to color texture. This is needed to do reversed when reading shadow values. So we got  hard and ugly shadows. Pic is brightened to show the artifacts more clearly. Shadow map resolution is 1024x1024 and look horrible.

Because I already use full color texture just for depth. VSM start look a really good option. If just packing depth to red and green channels and depth squared to blue and alpha channels the data amount statys a same but there is many advantages. This shadow map texture can be blurred with efficient Gaussian blur, hardware bilinear or anisotropic filtering can be used. Even mipmap chain can be created. Biggest con is that shadows can bleed light a bit in some cases but even that can be overcomed. For mobile standard version of VSM is not suitable becouse of branching but that can be fixed with ternary operation.
512x512 shadow map texture with VSM, filtered with 9x9 kernel Gaussian blur and hardware trilinear filtering.  Notice how VSM fix shadow acne and yagged edges without really big shadow map.
This run around 30fps on my device with sports with adreno205 GPU.
For vsm 256x256 is usually good enough.

Full source of VMS shader with one spotlight here
Shadowmap generation shader can be found here