May 15 2012
Let’s talk about shadows
There are a lot of different ways to create shadows in video games.
When I entered the game industry fifteen years ago, there were two standard ways to draw shadows: blob shadows and stencil shadows. (There was a third option as well: light maps, as popularised by Quake 2. But I’m not going to cover those since they were used for handling static lighting, not for real-time dynamic effects.)
Blob Shadows
Blob shadows are a very simple concept. If we have a moving object that we want to have appear to cast a shadow, all we have to do is to draw a sprite on the ground beneath it. This sprite was typically an indistinct, blurry oval, roughly matching the general size of the object it was “shadowing”. Its texture is where the term “blob” came from. In this shot, you can see a robot with a blob shadow. (That blob shadow is substantially larger than I would ever make it, personally. At this scale, it’s far too easy to tell that it’s just a simple sprite).
A tricky point about implementing blob shadows is making the shadow appear correctly over a ground surface; making it draw on top of an undulating terrain is a surprisingly tricky problem. It’s very easy to end up with a shadow sprite that clips through the ground or floats above it, or is visible through other objects between the shadow and the camera. Since the shadow is basically just a big flat sprite, you can’t reliably cast the shadow onto an extremely bumpy surface, or onto another object. You’re basically stuck with just a flat circle on a (more or less) flat ground.
Fifteen years ago, these were the usual way of putting dynamic shadows on movable objects in a game. As games became more sophisticated, we started finding ways to disguise how simplistic these shadows were. First by scaling the blob as the character animated (so as the character moved his leg forward, the circular shadow would stretch forward into an oval shape), and then by actually giving each character several different blob shadows, each projected down from a different part of the character’s body. This made the shadow seem to vaguely move along as the character animated in a much better way than the simple scaling approach. In Transformers, we gave each enemy robot (I seem to recall) four or five blob shadows, each anchored to a different part of the robot’s body. When rendered, these separately circular blob shadows appeared to merge together into a single amorphous blob that moved in a way which didn’t draw the player’s attention as being circular and static.
This technique is still around and being used today in new games. Just a few months ago I implemented it for use in an (unreleased) iPhone racing game, where we used vaguely car-shaped blob shadows under the cars. With some very sophisticated maths to try to make the shadow mimic the car’s rotation in mid-air, and projecting down onto the race track surface according to an angled light source and angled track. But fundamentally, if you ignore the fancy math for scaling and orienting it to the ground surface, it was still just a single blob shadow; just a flat sprite with a pre-drawn texture on it.
I seriously considered using blob shadows for MMORPG Tycoon 2. It certainly would have been faster to implement than what I’ve actually done. But all the foliage in the game would have caused problems, since the shadows would have sorted underneath the foliage and been almost invisible in many situations. (Even in modern games you occasionally see this problem, blob shadows vanishing under ground clutter)
Stencil Shadows
Also called “shadow volumes”, stencil shadows were the high-quality alternative to blob shadows. They’re not used as much today as they used to be, but it’s still an interesting technique.
The basic idea of stencil shadows is to computationally find the silhouette of an object from the light’s point of view, and then extrude that silhouette through space. This extruded object is the shadow cast by the object.
You then render this shadow object using a “stencil buffer”, and use the resulting stencil data to determine for each pixel in your screen image whether that pixel is inside or outside of the shadow volume. I worked on several games which used this sort of system. Usually this approach was only used for the shadow on the player character, or sometimes large boss enemies; it was really too CPU intensive for us to be able to afford to do it for all characters on-screen. And even when we did do it, we would use simplified versions of the visual models; usually just a series of boxes or elipses roughly approximating the character’s shape. Finding the silhouette and building renderable extruded geometry every frame was simply too expensive.
Another interesting point is that because of the way that stencil buffers work, the shadow was always hard-edged; each pixel was either in-shadow or out-of-shadow, so shadows couldn’t feather or soften with distance.
To do this, you had to render the shadow volume with a special shader, and you had to render any object which might receive a shadow with another special shader. This was always more expensive than normal rendering, so quite a lot of effort often went into determining precisely which triangles might receive a shadow, just for the purposes of figuring out which bits of world geometry needed to have the expensive shaders enabled.
Fun note: The further your shadow geometry is extruded, the longer it takes to render, both because it touches more pixels, because it will more often have to go through the expensive geometry clipping process, and also because it potentially hits more world geometry, thus requiring more stuff to render using the expensive shadow-receiver shader. But if your renderable geometry didn’t actually hit a shadow receiver (the ground underneath the character, for example, because the character was high up in the air from a jump or something and the shadow geometry wasn’t extruded far enough downward to reach the ground), then no shadow would be visible at all; the shadow would appear to suddenly pop into being as soon as the shadow caster moved within range. Most games tried to hide this pop-in by making the extruded shadow geometry be built like a spike; smoothly scaling down into a single point — kind of the opposite of the shadow volume being extruded from the torus in the image above. If you look at games from the early 90s, you’ll occasionally see games which do this; you can tell because you’ll see that shadows get smaller as objects move away from their cast shadows, instead of getting larger.
To my knowledge, no modern games use stencil shadows any longer. And that’s mostly because they’ve been completely replaced by the new favoured system(s): shadow maps, which are better in almost every way.







