I recently delivered a presentation on Hybrid Ray Traced Shadows (HRTS) at GDC 2015, as part of the “Advanced Visual Effects with DirectX 11 & 12” tutorial. If you weren’t fortunate enough to attend GDC, then you can catch up with what I was talking about right here!

As the name suggests, the technique combines ray tracing with conventional shadow mapping, to deliver extremely high quality contact-hardening style shadows. You end up with the best of both worlds, with razor sharp anti-aliased hard shadows interpolating to super soft shadows. The magic GPU HW feature required to make this work is Conservative Rasterization…

Storing Primitives for Ray Tracing

When approaching ray tracing, it is common to think about storing primitives in a Bounding Volume Hierarchy (BVH), such as an octree or kd-tree. While a hierarchy does allow the avoidance of many ray tests, it does need to be rebuilt (or reshaped) every frame on the GPU for dynamic objects. To add to these problems, hierarchy traversal tends to be quite slow, due to its inherent divergent nature. An interesting approach to ray tracing that avoids the use of a BVH, is to store primitives in a regular grid data structure as seen from the light’s point of view. Essentially you can think of this like a shadow map, but instead of storing depth, you store an array of triangles, as depicted below. Of course it is important to note that this kind of data structure would not scale to cater for a highly complex game scene, but instead would be more appropriate for a discrete dynamic object, such as the main game character.

Storing Primitives for Ray Tracing

Conservative Rasterization

Conservative raster is a cool new feature that came along with NVIDIA’s new Maxwell architecture, which means it is accessible today on GTX980, GTX970 and GTX960 boards. It allows rasterization to generate fragments for every pixel touched by a primitive as shown in the figure below. Conservative raster is an absolute requirement for deep primitive map rendering, to ensure that no triangle is missing from the array. If any single triangle is missing you end up with holes in the ray traced shadow result.

Conservative Rasterization

In addition to being available in DirectX 11.3 & 12, it is also possible to enable this feature in OpenGL and in DirectX 11:

Direct3D11

Use the NVIDIA NvAPI to create an ID3D11RasterizerState, the interface for this is shown below:

NvAPI_D3D11_RASTERIZER_DESC_EX NVAPI_RS_DESC;
NVAPI_RS_DESC.ConservativeRasterEnable = TRUE;  // Enable conservative raster
NvAPI_D3D11_CreateRasterizerState(
     pD3D11Device,
     (const NvAPI_D3D11_RASTERIZER_DESC_EX*)&NVAPI_RS_DESC,
     &m_pConservativeRaster );
OpenGL

Use the GL_NV_conservative_raster extension, the specs of which are located here:

https://d29g4g2dyqv443.cloudfront.net/sites/default/files/akamai/opengl/specs/GL_NV_conservative_raster.txt

Ray Tracing

To ray trace into the deep primitive map you need to:

·         Construct a ray from the world space position of a screen pixel to the light

·         Calculate primitive map texture coordinates (as you would for a shadow map)

·         Iterate over the triangles performing ray triangle intersections

The figures below show the difference between a regular shadow map result, and ray tracing:

Ray Tracing Ray Tracing

Anti-aliasing

It is of course possible to shoot additional rays to achieve an anti-aliased result, but not only is getting this correct quite tricky, it is also rather expensive. A simple trick is to make good use of a screen space AA technique such as FXAA. In figure 6 below, you can clearly see the smoothing benefit that this provides:

Anti-aliasing

Hybrid Approach

Hard shadows on their own may be useful in some niche circumstances, but the vast majority of games can benefit from contact-hardening style shadows that transition from being hard to soft as the distance between receiver and blocker increases. In order to achieve this you first need to generate a robust interpolation factor as described in the figure below:

Hybrid Approach

Below are a series of figures clearly showing the difference between regular PCSS and HRTS: Ray tracing produces crisp, detailed shadows that do not suffer from the under-sampled aliasing common with shadow mapping techniques. A very handy side benefit of this technique is it allows for increased values of depth bias without introducing Peter-Panning, which greatly reduces false shadowing acne.

Hybrid Ray Traced Shadows Hybrid Ray Traced Shadows
Hybrid Ray Traced Shadows Hybrid Ray Traced Shadows
Hybrid Ray Traced Shadows Hybrid Ray Traced Shadows

Call to Action

Because of great new GPU HW features like conservative raster, we can explore new approaches to problems. This new hybrid approach to shadows combines the best of both worlds, with razor sharp hard shadows transitioning to super soft shadows.