Shadow Maps (Work in Progress)
Shadow maps are a widely used technique in computer graphics that enable the real-time rendering of shadows for any object in a 3D scene. This is accomplished by rendering the scene from the perspective of a light source to generate a depth map of the scene, which is then used to determine which areas of the scene are in shadow.
Currently Implemented
-
Depth-only rendering pass.
-
Projective texturing.
-
Specialized shadow map shader.
-
Depth bias.
-
Slope scoped bias.
-
Box Sampling.
-
Dynamic texture resolution changes.
-
DirectX special sampler and rasterizer settings.
Role
Graphics & Engine Programmer
Engine
Custom C++ Engine
Tools and Languages
C++, HLSL, DirectX11, Visual Studio, RenderDoc, Nvidia Nsight.
Development Time
2 Months (In progress)
Concept
Shadow maps are a simple yet powerful technique. The concept is based on the fact that light can only illuminate objects that are within its reach. By capturing and utilizing this information, we can create realistic shadows in a scene. This is achieved by rendering a depth map from the perspective of the light source, which allows us to determine which objects are in shadow and which are not.
​
In the following picture, we can see how a spot blocked by the blue square has a depth of 0.6, because its depth is the closest depth recorded from the light's point of view. If we take the same point, and take its depth, but from the Eye's point of view, we will see its depth is greater (0.8). Something, which has a smaller depth (the blue box) is blocking the light from seeing this point.
Logic Behind Shadow Maps
Creating the Shadow Map
To generate the shadow map, the first step is to perform a depth pass-only rendering. This involves rendering the scene from the perspective of the light source, but with no need to output any color values. Therefore, a render target is not bound, but the depth buffer must be enabled and cleared to store the depth values of the scene.
​
Here, we can visualize the camera pointing down, and the depth buffer in the red rectangle on the right. The depth-buffer is rendered with a little processing so it's easier to see.
Visualizing the depth buffer
To get the depth from the Eye's point of view, some transformations need to take place from the world space into the light space.
Space Transformations
Artifacts
While shadow maps are an effective method for generating shadows, they can result in some issues if not implemented properly. One of the most common issues is "shadow acne," which occurs when there are shadows on a flat surface and some areas pass the depth test while others do not.
To address this issue, several techniques can be employed. One common approach is to apply a depth bias, which adjusts the depth values in the shadow map to prevent self-shadowing artifacts from appearing on the surface of the object.
Shadow Acne
Determining whether an object is in shadow or not involves comparing the depth value of the object in world space with the corresponding depth value in the shadow map. However, this process is prone to approximation errors, which can result in artifacts such as shadow acne or incorrect shadowing.
In the case of shadow acne, small differences between the depth values of the object and the shadow map can cause the object to incorrectly pass or fail the comparison test. For example, in the image provided, P1 appears to be in shadow due to the slight difference between its depth value and the corresponding value in the shadow map, while P2 is illuminated.
Depth Bias
Solved Shadow Acne
It's worth noting that there are different ways to apply depth bias.
The amount of bias required can vary depending on the slope of the surface being rendered. As the slope becomes steeper, more bias is needed to prevent self-shadowing artifacts.
To address this issue, a technique called slope-scaled depth bias can be used. This involves calculating the depth bias based on the slope of the surface being rendered, with steeper slopes requiring higher bias values.
Slope Scoped Bias
Improving Sampling
The quality of shadow maps is heavily influenced by their dimensions. Generally, shadow maps have higher resolutions than the actual render image, as having more pixels in the shadow map can improve sampling performance and reduce the occurrence of artifacts.
When dynamically changing the resolution of the shadow map, the quality of the shadows can also change. For example, if the resolution of the shadow map is decreased, the shadows may appear blocky or pixelated due to the lower number of pixels available to represent the scene. On the other hand, increasing the resolution of the shadow map can improve the accuracy of the shadows, but can also increase the computational cost of rendering the scene.
Here we take a closer look at the object's shadow and what happens when dynamically changing the shadow maps resolution:
Changing Shadow Map's Resolution
To improve the quality of shadows, different sampling methods can be used when rendering the shadow map. One such method is box sampling, which involves sampling the texture in a "box" shape and averaging the values. This can help to produce smoother and more realistic shadows by reducing the visibility of individual texels in the shadow map.