Tag Archives: Shadows

Percentage Closer Filtering for Shadow Mapping

This is a technique for making softer shadows when doing shadow mapping. It works by filtering the result of the depth comparison. So when comparing a depth, some depths around should also be compared and the result should be averaged. This will give a softer look on the shadow edges.

An example of the the soft shadows when using PCF Shadow Mapping

It can be implemented as simple as this in a the pixel shader:

float result;
result = shadow2DProj(shadowMap,texCoord+offset[0]);
result += shadow2DProj(shadowMap,texCoord+offset[1]);
result += shadow2DProj(shadowMap,texCoord+offset[2]);
result += shadow2DProj(shadowMap,texCoord+offset[3]);
result /= 4.0; // now result will hold the average shading

The samples are often either taken in a grid-based square around the original sample location or randomly scattered around it.


NVIDIA has built in hardware support for doing bilinear interpolation between four samples.

ATI has fetch4 which will fetch four texture samples at the same time.  

The original paper for PCF:

A technique that is similar (percentage-closer soft shadows)

A paper including lot’s of shadow mapping information, including different ways to do PCF (the image in this article is borrowed from this presentation):

Basic Shadow Mapping

Shadow mapping works in that it checks if a point is visible from the light or not. If a point is visible from the light then it’s obviously not in shadow, otherwise it is. The basic shadow mapping algorithm can be described as short as this:

  1. Render the scene from the lights view and store the depths as shadow map
  2. Render the scene from the camera and compare the depths, if the current fragments depth is greater than the shadow depth then the fragment is in shadow
Shadow mapping example

It’s the implementation of it that is hard.

The two big problem areas with shadow mapping:

  • Hard to select an appropriate bias (epsilon)
  • Hard to get rid of artifacts at shadow edges

Projective texturing ( the method used to transform the fragment depth to the light space (where the shadow map is) for comparision)

OpenGL fixed-function pipeline implementation of shadow mapping:

A GLSL implementation of shadow mapping (in one of the posts)

Another GLSL shadow mapping shader:

DirectX9 shadow mapping example with source

Nvidias implementation of shadow mapping with source for both OpenGL and DirectX.

Shadow mapping in XNA

Forward Shadow Mapping

This technique for shadow mapping does the reverse when comparing depths. Instead of the normal case of comparing depths in light space, this method suggest that the comparison should be done in eye space. This requires the depth buffer from the lights’ view and from the camera’s view at the time of the comparison. This method is probably most useful when doing deferred lightning.

Forward Shadow Mapping

Link to the paper “Forward Shadow Mapping”

Variance Shadow Mapping

An different approach to store the shadow map to gain softer shadows with less artifacts. The abstracts says the following:

“Shadow maps are a widely used shadowing technique in real time graphics. One major drawback of their use is that they cannot be filtered in the same way as color textures, typically leading to severe aliasing. This paper introduces variance shadow maps, a new real time shadowing algorithm. Instead of storing a single depth value, we store the mean and mean squared of a distribution of depths, from which we can efficiently compute the variance over any filter region. Using the variance, we derive an upper bound on the fraction of a shaded fragment that is occluded. We show that this bound often provides a good approximation to the true occlusion, and can be used as an approximate value for rendering. Our algorithm is simple to implement on current graphics processors and solves the problem of shadow map aliasing with minimal additional storage and computation.”

Variance Shadow Mapping

The original paper and demo with source code:

Nvidias implementation and description of the algorithm (source code for DirectX10 can also be found on the same page):

Some more info from the author: