Shadows

Add shadows to your simulation for a more graphically immersive world.


Shadows are an important part of being graphically immersed into the training world. They often provide important training value, such as judging the height of the hook on a crane. Shadows are available for three light types: infinite directional lights, finite directional lights and spotlights.

In order to keep the amount of video memory used by the shadows under control, the integrator can choose the Texture Resolution and the Texture Layer Count of the shadow texture array, both located in the Adaptive Feature Controller extension's Properties panel, under ParametersShadows. When there are more lights that cast shadows than there are layers in the shadow texture array, you can split the layers of the shadow texture array into the necessary number of shadow maps. This allows the support of a large number of shadow maps, at the expense of the quality of the shadows.

One shadow map is created for each finite directional light and for each spotlight. The infinite directional lights use the Cascaded Shadow Map (CSM) technique, namely using multiple shadow maps, depending on the number of viewports as well as the number of Cascaded Shadow Map Splits (CSMS).

Cascaded Shadow Map (CSM)

The CSM technique is used on finite directional light to ensure that the shadows near the camera are of good quality, yet provide some shadows on objects that are very far from the viewer. In order to achieve this goal, you can create multiple Cascaded Shadow Map Splits that become larger, the further they are for the viewer. Each CSMS generates its own shadow map.

Since both the orientation of the viewer and the orientation of the light are used to place the CSMS, this technique works best when the orientation of the viewer and the orientation of the light are perpendicular.

The size and placement of the CSMS are automatic and configured by the Adaptive Feature Controller extension. The ParametersShadowsNumber of Splits field determines the number of CSMS for a viewer and infinite directional light pair. The Ratio of Splits parameter determines the dimension of each CSMS.

Shadow Performance

Drawing each shadow map implies traversing and drawing the scene completely on the off-screen shadow texture array. This has a significant cost, similar to drawing all the objects of the scene in the window.

For example, assume you are creating a driving simulator. You have two infinite directional lights casting shadows in the environment: the sun and the moon. In a sports car mechanism, you have four spotlights casting shadows representing the vehicle's front and back headlights, as well as three mirrors: the driver-side mirror, the passenger-side mirror and the rear-view mirror. Among other objects, there is a mailbox in the scene. Assuming a default configuration with an Adaptive Feature Controller that has ParametersShadows > Number of Splits set to 4, there will be 36 shadow maps to fit in the shadow texture array and to redraw every frame. The simple mailbox will be culled and drawn 37 times to refresh the scene in order to achieve the best quality.

Note The formulas below are overly simple. Since the graphics engine is complicated, there is no simple way to compute the performance cost of drawing the shadow maps.

Assume that the driving simulator scene was built without consideration for the shadows. It was tweaked to draw in exactly 15 ms without shadows. Once shadows are enabled, it is safe to assume that the scene will take rough 37 * 15 ms = 555 ms to draw. Just like that, the frames per second (FPS) went down from 60 FPS to slightly less than 2 FPS. This is not acceptable. Removing objects from the scene is the simplest fix. In order to keep the best-looking shadows and remain at 60 FPS, you would need to discard most of the objects in the scene. If there were 1000 objects in the scene before, you'd end up with 1000 / 37 = 27 objects remaining. This is not acceptable either, but removing objects from the scene is necessary: there is no option where the shadows have an insignificant cost.

Let us consider at some options:

  • Reducing ParametersShadowsUpdate Rate to 2 means that two shadow maps will be re-drawn every frame. This will greatly improve the performance, but the rendering will use stale shadow maps. Depending on the speed of the various objects in your simulator, you may afford a lower update rate.
  • Setting the ParametersShadowsView Distance to 40 will cull a lot of the further objects and their shadow draw queues.
  • Setting the Casts Shadows flag to False for smaller or further objects will remove them from the shadow draw queues.

Disabling the Shadows for a Monitor or Mirror

There is no automatic system that disables the shadows from a monitor or a mirror, but it can be done manually.

The Mirror extensions uses a Monitor to internally draw on a texture, with a customized look-through camera that moves with the viewer. The Monitor extension creates a VxGraphics viewport that internally creates a new set of CSMS for each infinite directional light.

The viewport created for a Monitor extension has the naming convention <monitor> Viewport, where <monitor> is the name of the extension in the Editor. In your Adaptive Feature Controller extension configuration, you can add a View Distance item (within ParametersShadows) with the Viewport Name set to <monitor> Viewport.

Then, deselect the Enable checkbox on this item in the Editor to disable the shadows for the Monitor.

CSMS and Performance

Changing the configuration of the CSMS greatly impacts your simulation, among them:

  • Reducing ParametersShadows > Number of Splits to 2 may improve the GPU performance, but you will notice coarser shadows.
  • Reducing ParametersShadows > Ratio of Splits to a small value such as 1.5 may improve the CPU performance when the Update Rate is low, but will reduce the CPU performance when the Update Rate is high.

In some cases, the performance may be improved for some viewpoints and reduced in other viewpoints. Typically, we do not recommend changing the CSMS in order to improve the performance.

GPU Costs and Shadows

Most of the techniques described above help both with the performance of the GPU and the CPU. There are some basic options that only target the GPU performance:

  • Reducing ParametersShadows > Texture Resolution helps with video memory usage, texture fetches and writes.
  • Reducing ParametersShadows > Filtering Quality reduces the number of texture fetches.

Optimize Performance with Shadow Volumes

A shadow volume is a low polygon version of an asset that occupies the same space as the original model but only for the purpose of generating dynamic shadows. This simplifies the calculations and makes drawing the shadow less costly in terms of computing power.

Mesh with shadow volume (left) and without (right)Original mesh (left) compared to shadow volume mesh (right)

To create a shadow volume for a model, add one or more empty nodes and rename them “Shadow Volume”. Deselect the Visible checkbox but keep the node(s) casting shadows. Use a low polygon graphic geometry in the node, and leave the graphic material field empty (the node is invisible anyway). Deselect all Cast Shadow checkboxes on the nodes of your detailed 3D model. The computer will only use the low polygon model to calculate the shadow, instead of figuring out all the interactions between the lighting and the complex structure of the visible model.

Note Nothing prevents the low-poly graphic geometry used for a distant Level of Detail to do double-duty as a shadow volume. It is not necessary to make a custom one; several nodes can point to the same graphic geometry.

The values in your Graphics Gallery will then look something like this example:

Node - Main Model

  • Visible: On
  • LOD 0: Geo 1 (high poly) and Graphic Material
  • LOD 1: Geo 2 (med poly) and Graphic Material
  • LOD 2: Geo 3 (low poly) and Graphic Material
  • Cast Shadow: Off (in all LODs)
  • Receive Shadow: On (in all LODs)

Node - Shadow Volume

  • Visibility Off
  • LOD 0: Geo 3 (low poly) and no Graphic Material
  • Cast Shadow: On (in all LODs)
  • Receive Shadow: Off (in all LODs)
It is not necessary to create shadow volume nodes for every node of a model. Rather, this technique is primarily recommended for implementing visually complex meshes, as the process can be time-consuming.