Screen Space Soft Shadows
Screen Space Soft Shadows
The aim of this work is to introduce a new soft shadow mapping algorithm for generating
variable-sized penumbrae that minimizes texture lookups in order to maximize performance.
This method is called Screen Space Soft Shadows and it is based on blurring the shadows
from the observer's point of view by using an anisotropic Gaussian filter of variable size.
The aspect ratio of the anisotropic Gaussian filter is determined by using the normal at the
point being rendered. The size of the area affected by the filter, which generates softer or
sharper penumbrae, varies per pixel and depends on the amount of light potentially received
from the area light source. This factor is determined by the visibility of the area light from the
point being rendered. The formula used to estimate how much light is received is:
Wpenumbra is the final width of the penumbra, Dreceiver and Dblocker are the distances of
the receiver and the blocker to the light. Finally, Wlight is the size of the area light.
These are the steps we have to follow for each light source:
1. Calculate the standard shadow map (Smap) and a "dilated" version (Smap)
of the shadow map. In order to calculate the Shadow Maps, we create a coarser version of
the shadow map: each pixel of the coarse shadow map will approximate a block of pixels of
the standard shadow map. The criterion used for this approximation is the minimum value
(closest to the light). The dilation is performed in light space, by applying an isotropic
min-filter to the original shadow map, after it is computed. Given that this filter is separable, it
is computed efficiently as two one-dimensional filters.
The amount of dilation is proportional to the size of the area light source because the size of
the penumbra is also proportional to the size of the light source. The user has to apply a
constant factor to the amount of dilation, because the size of the penumbra is also
proportional to the distance between the shadow caster and the shadow receiver. This factor
is interpreted as the maximum distance to the occluder possible in the scene. If this
parameter is too small, penumbrae will not be completely smooth. On the other hand, if the
parameter is too large, the resulting penumbrae will be less accurate.
2. Render the scene from the observer's point of view and calculate the
following elements in the same rendering pass: the shadows without penumbrae (or
hard shadows), the depth buffer, a normal buffer and the shading of the scene
(without shadows). The distances map is also calculated in the same rendering pass, it is a
screen-aligned texture that contains, per pixel, the distance of the shadow to its potential
occluder and its distance to the observer. This is computed by rendering a full screen quad
so that every pixel in the screen is evaluated. Distances to the occluder are computed by
transforming the point being evaluated to the light space. This way, its depth value can be
compared directly with the depth of the coarse occluder. For optimization purposes, the
distances map also stores a mask determining which pixels will never receive neither a
shadow nor a penumbra. The shadow mask is useful to reduce texture lookups and improve
performance.
3. Deferred shadowing: render a full screen quad with our custom anisotropic
Gaussian blur filter to blur the hard-edged shadows in screen space and to combine them
with the shaded scene. The per-pixel size of the area affected by the blurring kernel is
calculated using the data in the distances map.
Applying the Gaussian Filter Determining the size of the penumbrae. This step generates the
penumbra by applying an anisotropic Gaussian blur filter in screen space. The size of the
region affected by the kernel varies per pixel depending on:
- The distance of the shadow to the occluder.
- The distance of the light source to the occluder.
- The size of the light source.
We derive the equation 1.0 by adding the distance of the pixel to the observer to the
computations, in order to determine the size of the area affected by the filter in screen
space:
For each sample accessed to perform the Gaussian filter, their distance to the observer is
taken into account to discard samples whose distance to the current pixel is greater than a
certain threshold. This is used to prevent the filter kernel from taking into account parts of the
scene that are close in eye space but are far away in world space. It also avoids having to
filter the shadows with the contents of the background. The number of samples taken by
the Gaussian filter determines both the quality of the shadows and the performance. A
good optimization, is to decrease the number of samples by the blurring kernel decreases.
To determine the shape of the anisotropic filtering, the normal of the current pixel is fetched
from the normal buffer. Using this normal, the local tangent space is calculated and used to
determine the local 1-, y- and z-axes. Projecting these axes to eye space allows us to
determine the shape and orientation of the ellipse which defines the anisotropic filter.
Finally, after the vertical blurring pass is performed, the penumbra has already been
calculated so the pixel shader combines it with the unshadowed scene C to create the
final image, with complete shadows with penumbrae.