How to see shadows from distant objects

Mar 15, 2021.Knowledge

How to see shadows from distant objects

Let’s say you’re making a big city or a large open world landscape, and you have a large feature in the far distance that should be casting a shadow. For some reason, your tall building or mountain doesn’t cast shadows, though! Let’s learn a little bit about how we calculate dynamic shadows from the directional light, and what systems we have in place to make sure far-away objects can cast shadows in a performant way.

Here’s a high-level overview of how directional lights cast dynamic shadows in a raster (not raytraced):

Cascading Shadow Maps

Dynamic shadows cast by the directional light use a system called Cascading Shadow Maps.

The system divides the scene from the camera outward into cascades up to the Dynamic Shadow Distance Movable or Dynamic Shadow Distance Stationary (depending on the mobility setting of the light) into sections based on the number of cascades the light is using. The distribution and transitions between these cascades can be controlled by settings on the light itself. You can read more about those in our documentation on Directional Lights .

The light will then render a depth map from the perspective of the light in order to cast shadows, one for each section.

So, if a light has a Dynamic Shadow Distance of 15000, and 3 cascades, then the first cascade holds the shadow information of everything from 0 to 4999 units away from the camera, the next will cover everything from 5000 to 9999 units away from the camera, and the final cascade will cover 10000 to 15000 units.

Cascading shadow maps have the added benefit of rendering the shadows for everything as-is. If a tree sways, the shadow will also sway. If a character morphs or animates, the shadow will morph and animate accordingly.

The downside is that this method of drawing shadows can be expensive to render, and the expense increases with the number of cascades used and the number of objects which have to be drawn into the shadow maps (which increases as a function of the dynamic shadow distance).

Cascading shadow maps have a fixed resolution (set by the cvar r.Shadow.MaxCSMResolution), so as the dynamic shadow distance increases, then the effective texel density of each cascade will decrease causing blurry shadows. You could increase the number of cascades, but as mentioned earlier this can have an adverse effect on performance.

What, then, can we do to ensure our distant objects cast shadows without sacrificing dynamic shadow resolution or GPU performance?

Distance Field Shadows

The first option is to use Distance Field Shadows, which are discussed more thoroughly in our documentation on Distance Field Soft Shadows and Using Distance Field Shadows .

Distance field shadows cover the distance between the Dynamic Shadow Distance and the Distance Field Shadow Distance setting, so they begin after the cascading shadow map shadows.

Distance Fields have an added memory and cook cost, since we have to generate a mesh distance field for each static mesh and update the global distance field when things move around.

However, since these shadows are calculated based on a static and mathematical representation of the geometry, they’re much cheaper to calculate compared to depth-based dynamic shadows.

Since the distance field representation of a static mesh is non-deforming (IE unaffected by world position offset), the distance field shadow cast by a tree won’t sway. However, since these shadows are far off in the distance, this lack of motion is unlikely to be noticeable.

Note: single-sided or thin meshes won’t cast distance field shadows, since the distance field for those pieces won’t get generated. This can happen with CAD-derived surfaces.

Far Cascades

The other option that you can use for particularly distant shadows, or very large objects that cast shadows, is to use a Far Cascade. This is an additional cascading shadow map, but actors must be set to cast shadows in the far cascade. The performance benefit is that we only have to calculate shadows for a discrete number of actors which we know need to cast those large shadows. For example, the skyscraper would be enabled to cast shadows in the far cascade but the trash can outside its front door would not be.

Far cascades have the added benefit of covering hundreds of thousands of units away from the camera. You could consider using both distance field shadows, and the far cascade to cover all your needs.

How to Enable Far Cascades

  1. Ensure you’re using a Movable directional light
  2. In the light’s Cascaded Shadow Maps settings set the Far Shadow Count to 1:


How to Opt-In to the Far Cascade

  1. Select the static mesh actors you want to cast shadows in the far cascade. Remember, these should be exceptionally large meshes that can be seen from a great distance.
  2. In the static mesh actor’s Lighting sets, click the “Far Shadow” checkbox: