Transparent shadows using stippling
Add comment!October 8th, 2009
Most modern games use a form of depth-map shadow mapping, because it's efficient on modern graphics cards, and simple to implement. However, it doesn't easily support transparent surfaces. This leads to some inappropriately harsh shadows on materials that are meant to look softer, such as leaves in trees:
Here are the shadows isolated:
To soften the shadows, I decided to approximate translucency. In practical terms, that means that shadows closer to the leaves should be fairly faint, but shadows farther away will be dark. To approximate that when rendering the depth map, I drew the leaves four times at different levels of opacity, moving away from the light source. That is, at their original position they cast a shadow at 25% opacity, at a slightly farther position they cast a shadow at 50% opacity, and so on.
To simulate transparent shadows, I used 'stippling': a method of approximating transparency by using patterns of opaque dots. This is similar to how I used to simulate levels of gray when making black and white games in Hypercard -- for example, medium gray is approximated by alternating black and white pixels in a checkerboard pattern. This is easy to achieve in a GLSL pixel shader like this:
if(int(gl_FragCoord.x+gl_FragCoord.y)%2==0){
discard;
}
This shader excerpt displays a checkerboard stippling pattern by only drawing every other pixel. It checks if the sum of the pixel coordinates is even or odd -- if it's even, the pixel is discarded (not drawn). If it's odd, it is drawn as usual. Here's a close-up of the different stippling levels in the tree shadow.
Our shadow maps are blurred and supersampled to remove aliasing artifacts, and this conveniently also smooths out these stippled shadows. Here are the new softened shadows (on the right).
Here it is with all of the shading enabled. It's a subtle difference with these trees and these lighting conditions, but every bit counts!
Here it is again from another angle:
This is another effect that took very little time to implement, and requires no extra real-time rendering resources. This is why even though it's a subtle effect, I thought it was worth showing to you! Stippled shadows also work well for adding shadows to particle effects like smoke and dust, and to transparent materials like glass or gossamer. Can you think of any other uses for this technique?