{"id":2524,"date":"2012-05-15T20:16:13","date_gmt":"2012-05-15T10:16:13","guid":{"rendered":"http:\/\/www.vectorstorm.org\/?p=2524"},"modified":"2012-05-16T12:56:23","modified_gmt":"2012-05-16T02:56:23","slug":"lets-talk-about-shadows","status":"publish","type":"post","link":"https:\/\/www.vectorstorm.com.au\/2012\/05\/15\/lets-talk-about-shadows\/","title":{"rendered":"Let’s talk about shadows"},"content":{"rendered":"
There are a lot of different ways to create shadows in video games.<\/p>\n
When I entered the game industry fifteen years ago, there were two standard ways to draw shadows:\u00a0 blob shadows and stencil shadows.\u00a0 (There was a third option as well:\u00a0 light maps, as popularised by Quake 2.\u00a0 But I’m not going to cover those since they were used for handling static lighting, not for real-time dynamic effects.)<\/p>\n
Blob shadows are a very simple concept.\u00a0 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.\u00a0 This sprite was typically an indistinct, blurry oval, roughly matching the general size of the object it was “shadowing”.\u00a0 Its texture is where the term “blob” came from.\u00a0 In this shot, you can see a robot with a blob shadow.\u00a0 (That blob shadow is substantially larger than I would ever make it, personally.\u00a0 At this scale, it’s far too easy to tell that it’s just a simple sprite).<\/p>\n
A tricky point about implementing blob shadows is making the shadow appear correctly over a ground surface;\u00a0 making it draw on top of an undulating terrain is a surprisingly tricky problem.\u00a0 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.\u00a0 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.\u00a0 You’re basically stuck with just a flat circle on a (more or less) flat ground.<\/p>\n
Fifteen years ago, these were the usual way of putting dynamic shadows on movable objects in a game.\u00a0 As games became more sophisticated, we started finding ways to disguise how simplistic these shadows were.\u00a0 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.\u00a0 This made the shadow seem to vaguely move along as the character animated in a much better way than the simple scaling approach.\u00a0 In Transformers<\/a>, 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.\u00a0 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.<\/p>\n This technique is still around and being used today in new games.\u00a0 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.\u00a0 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.\u00a0 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;\u00a0 just a flat sprite with a pre-drawn texture on it.<\/p>\n I seriously considered using blob shadows for MMORPG Tycoon 2.\u00a0 It certainly would have been faster to implement than what I’ve actually done.\u00a0 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.\u00a0 (Even in modern games you occasionally see this problem, blob shadows vanishing under ground clutter)<\/p>\n Also called “shadow volumes”, stencil shadows were the high-quality alternative to blob shadows.\u00a0 They’re not used as much today as they used to be, but it’s still an interesting technique.<\/p>\n 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.\u00a0 This extruded object is the shadow cast by the object.<\/p>\n 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.\u00a0 I worked on several games which used this sort of system.\u00a0 Usually this approach was only used for the shadow on the player character, or sometimes large boss enemies;\u00a0 it was really too CPU intensive for us to be able to afford to do it for all characters on-screen.\u00a0 And even when we did do it, we would use simplified versions of the visual models;\u00a0 usually just a series of boxes or elipses roughly approximating the character’s shape.\u00a0 Finding the silhouette and building renderable extruded geometry every frame was simply too expensive.<\/p>\n Another interesting point is that because of the way that stencil buffers work, the shadow was always hard-edged;\u00a0 each pixel was either in-shadow or out-of-shadow, so shadows couldn’t feather or soften with distance.<\/p>\n 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.\u00a0 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.<\/p>\n Fun note:\u00a0 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.\u00a0 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;\u00a0 the shadow would appear to suddenly pop into being as soon as the shadow caster moved within range.\u00a0 Most games tried to hide this pop-in by making the extruded shadow geometry be built like a spike;\u00a0 smoothly scaling down into a single point — kind of the opposite of the shadow volume being extruded from the torus in the image above.\u00a0 If you look at games from the early 90s, you’ll occasionally see games which do this;\u00a0 you can tell because you’ll see that shadows get smaller as objects move away from their cast shadows, instead of getting larger.<\/p>\n To my knowledge, no modern games use stencil shadows any longer.\u00a0 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.<\/p>\n <\/p>\n As hardware has advanced, the power of graphic cards and rendering speeds have accelerated far faster than regular CPU processing.\u00a0 As a result, we’ve started to push all sorts of processing over to graphic cards whenever possible, since the graphic cards often have a lot more processing time available.\u00a0 Shadow maps are one of those cases.<\/p>\nStencil Shadows<\/a><\/h2>\n
Shadow Maps<\/h2>\n