October 25th, 2024
Towards the end of Wim Wenders’s excellent Perfect Days, the protagonist Hirayama is drinking beer under a bridge after he has seen a Businessman courting his crush. Suddenly the Businessman joins him under the bridge. As it turns out, things aren’t actually that simple but the point is their conversation takes them to some fundamental questions:
Businessman: Shadows. Do they get darker when they overlap?
Hirayama: Not sure.
Businessman: So many things I still don’t know… That’s how life ends… I guess.
Hirayama: Let’s find out now.
Businessman: What?
Then they step into to the light of a street lamp and investigate their shadows (the full scene):
Even though the Businessman sees no difference, Hirayama is convinced the overlapping shadows do become darker. “It has to get darker to make sense.” What a moving scene.
Unfortunately Hirayama is mistaken. Shadows don’t get any darker there. There’s just one light source, and relatively far away, so the shadow is simply an absence of light. It doesn’t matter how many times the light is blocked.
When it comes to 3D videogames, shadows are something else. It’s easy to paint dark blob under some character’s feet and assume everything else is lit. Perhaps Hirayama was recalling the blob shadow in Metal Gear Solid that does become darker when it overlaps with others?
In the real world, shadows simply exist but in games they are both engineered and designed. They must run well but also look good. I find this relationship fascinating and I’m going to show you why. Let’s start simple.
You can draw a shadow image to the screen before you draw a character. I’m not talking about shadow sprites like in Duke Nukem 3D but literally a 2D image without any scaling. This works if the character is in front of everything like in Winter Gold or MDK.
I said it was simple.
OK now in 3D. Draw a dark disc under the character. Done.
Well, you should also align the shadow disc with the ground and also decide how to handle situations where the shadow would reach over a ledge. For example in Super Mario 64, the blobs are drawn using a special hardware feature that effectively clips the shadow to show up only on the ground plane.
The blob shadow can also be animated. In Super Mario 64 it becomes smaller when jumping and in Metal Gear Solid it changes shape. If you’re feeling ambitious, you can also solve the shadow-over-a-ledge issue by projecting the blob quad like a decal.
The blob is just a texture and usually textures can be rendered to at runtime. So render the character from the top and use that instead of a dark circle. This works great in Crash 3 (video) but not so well in Soldier of Fortune because they kept the shadow resolution so low.
Note that this is distinct from shadow mapping where a depth map is rendered from the light’s point of view. Here we render only a black & white image that is used as a texture. So in a sense we’re talking about a 1-bit shadow map.
How could we make the shadows sharper?
One intuitive option is to flatten a shadow caster on a plane by projecting it away from the light. Then render it the second time but now in black. They are usually kept opaque to hide how object parts are drawn on top of another. Naturally the shadow will be correct only on a flat floor.
Some early flight simulators draw a top-down flat shadow when on a runway. During my research I expected to see examples where the shadow is also seen when in flight but couldn’t find any.
Visually these look the same as black stencil shadows cast on a flat plane.
David Braben’s 1987 Virus on Acorn Archimedes and other home computers draws spaceships that cast top-down shadows on terrain.
A more elaborate example is Interstate ’76. There they tilt and stretch a planar shadow to match the ground slope. The shadows occasionally penetrate the ground but are pretty convincing overall. Interestingly, the below software-rendered screenshot has slightly transparent shadows while the hardware accelerated ones are pitch black.
They also had the courage to try to project shadows for large objects like bridges which isn’t, well, entirely successful.
But how do you cast shadows on any kind of scene?
This approach bears a lot of similarity to Planar shadows with a render texture presented earlier but works on surfaces of any shape. The game renders a shadow texture from the top but instead of showing it on a flat plane, the texture is projected to other objects. Think of it as the Bat-Signal but pointed straight down from the sky.
Shadows like this can be made really sharp but they can look strange on vertical surfaces and occassionally even appear on the ceiling. See this gameplay video of Sonic Adventure 2: Battle (2001, GameCube).
This technique also works great for trees:
Projected shadows can show through objects which makes them suitable only for special cases. Shadow maps are something you can use anywhere.
The de facto approach to shadows. The game draws a depth image, the shadow map, from the point of view of the light and reads from that image when rendering the world. This is easy to do since you can reuse the game engine’s regular rendering code.
The limited resolution of the shadow map gives rise to well-known artifacts with inventive names such as “Peter Panning” and “shadow acne”. Many tricks have been proposed to allocate more shadow map area to surfaces near the camera where the extra resolution is needed the most. Shadow maps usually need some tweaking to look right.
Before shadow maps became dominant, there was a popular competitor.
The has-been approach to shadows. Stencil shadows draw sharp shadows on any kind of surface. They create a unique film-noir look that’s hard to emulate with shadow maps. Most well-known example is of course Doom 3 with its dark rooms:
Stencil shadows are based on the idea of shadow volumes, invisible geometry that cuts the world into lit and shadowed spaces. The game applies lighting only on pixels that don’t lie inside a shadow volume.
Stencil shadows need the world to be drawn many times to work. Simplified a bit, the game first draws the whole world with ambient lighting. Then for each light, all the shadow volumes, followed by the world again, affecting only unshadowed pixels. The volumes are drawn with different stencil operations set for front and back faces. It’s a lot of pixels to draw.
Possibly the earliest shipping game with stencil shadows is Severance: Blade of Darkness from 2001 whose shadows look great.
Reading the Edge UK edition March 2001 review (pdf) of the game makes it clear that despite the graphics advancements, the world wasn’t ready for a soulslike back then.
Stencil shadows are not used much nowadays. One reason is their unpredictable runtime cost. The cost is dependent on how large the volume is on screen and therefore varies a lot. Also an optimized algorithm was patented. For Doom 3, Id Software apparently reached some sort of a deal.
Stencil shadows don’t need to be sharp. Another game from 2001, Silent Hill 2 on the PlayStation 2, blurred the stencil shadows afterwards as seen above. It looks pretty much perfect on the console.
What if the shadows are cast by a simpler model than what’s shown on screen? For example in Zelda on the Nintendo 64, Link’s feet cast shadows even though nothing else does:
One unique approach is seen in Hyperblade where players on a futuristic hockey arena cast planar shadows as simple animated shapes.
Vertex colors and lightmaps are techniques to capture lighting of a game level. They have been used in many games as the only way to show large scale shadows, which is why I’ve included them here.
Ico shows how sophisticated shadows can look with just old school per-vertex lighting.
For low-poly maps even sharp shadows can be represented with vertex colors. A prime example is Tony Hawk Pro Skater 2 (2000, Playstation) which looks amazing considering the simplicity of the technique.
Lightmaps are the classic way to store level lighting and shadows. Instead of storing a color for each vertex, there’s a second set of textures that represent only lighting. The resolution can vary per area, making the shadows more accurate where needed. On the other hand, lightmaps consume more memory than vertex colors.
Lightmaps were popularized by Quake (1996, PC) and this is how they look.
That concludes our look into traditional shadow techniques. Let’s talk a bit about lighting in general next.
Modern games use the traditional techniques when appropriate. Some examples:
In the beginning we established that shadows are formed by a lack of light. If the game really tries to simulate physically correct lighting then shadows will naturally appear. Even small geometric details will cast accurate shadows, unlike in shadow maps. Big lamps will naturally create soft shadows and indirect light will brighten dark corners. An incredible amount of time and money have been invested in ray tracing algorithms and hardware to make this dream reality.
In practice modern games have such complex scenes the above simulated solution has to be approximated. For example in the ray-traced shadows of Alan Wake 2 (2023) each pixel receives lighting only from a single randomly chosen light. The result is eventually fed to a denoiser that intelligently smooths out the noisy picture. See the whole presentation for details. Therefore even ray-traced shadows won’t be “perfect” and will have their own look, depending on the tradeoffs made.
Finally, the obvious option.
Sometimes your priorities are elsewhere.
In the movie scene, when Hirayama is carefully studying the shadows, his new friend makes an observation:
Businessman: You’re really into this.
As computer graphics enthusiasts, I think we can symphatize.
All screenshots provided by MobyGames unless noted otherwise. Thanks to mankeli for detailed notes on an early draft of this article. Thanks to noby, msqrt, shaiggon and Warma for feedback.
Update on Oct 31st, 2024: Corrected the shadow map section to refer to Far Cry instead of Half-Life 2. The latter uses projective texture mapping with a black & white texture for its characters. Thanks to Max Lebled for pointing out this error.