Reader small image

You're reading from  Mastering Graphics Programming with Vulkan

Product typeBook
Published inFeb 2023
PublisherPackt
ISBN-139781803244792
Edition1st Edition
Right arrow
Authors (2):
Marco Castorina
Marco Castorina
author image
Marco Castorina

Marco Castorina first got familiar with Vulkan while working as a driver developer at Samsung. Later he developed a 2D and 3D renderer in Vulkan from scratch for a leading media-server company. He recently joined the games graphics performance team at AMD. In his spare time, he keeps up to date with the latest techniques in real-time graphics.
Read more about Marco Castorina

Gabriel Sassone
Gabriel Sassone
author image
Gabriel Sassone

Gabriel Sassone is a rendering enthusiast currently working as a Principal Rendering Engineer at Multiplayer Group. Previously working for Avalanche Studios, where his first contact with Vulkan happened, where they developed the Vulkan layer for the proprietary Apex Engine and its Google Stadia Port. He previously worked at ReadyAtDawn, Codemasters, FrameStudios, and some non-gaming tech companies. His spare time is filled with music and rendering, gaming, and outdoor activities.
Read more about Gabriel Sassone

View More author details
Right arrow

Revisiting Shadows with Ray Tracing

In this chapter, we are going to implement shadows using ray tracing. In Chapter 8, Adding Shadows Using Mesh Shaders, we used traditional shadow mapping techniques to get the visibility from each light and use that information to compute the shadow term for the final image. Using ray tracing for shadows allows us to get more detailed results and to have finer-grained control over the quality of results based on the distance and intensity of each light.

We are going to implement two techniques: the first one is similar to the one used in offline rendering, where we shoot rays to each light to determine visibility. While this approach gives us the best results, it can be quite expensive depending on the number of lights in the scene.

The second technique is based on a recent article from Ray Tracing Gems. We use some heuristics to determine how many rays we need to cast per light, and we combine the results with spatial and temporal filters...

Technical requirements

By the end of this chapter you will learn how to implement basic ray-traced shadows. You will also become familiar with a more advanced technique that is capable of rendering multiple lights with soft shadows.

The code for this chapter can be found at the following URL: https://github.com/PacktPublishing/Mastering-Graphics-Programming-with-Vulkan/tree/main/source/chapter13.

Implementing simple ray-traced shadows

As we mentioned in the introduction, shadow mapping techniques have been a staple of real-time rendering for many years. Before the introduction of ray tracing capabilities in GPUs, using other techniques was simply too expensive.

This hasn’t prevented the graphics community from coming up with clever solutions to increase the quality of results while maintaining a low cost. The main issue with traditional techniques is that they are based on capturing depth buffers from the point of view of each light. This works well for objects that are near the light and camera, but as we move further away, depth discontinuities lead to artefacts in the final result.

Solutions to this problem include filtering the result – for instance, using Percentage Closer Filtering (PCF) or Cascade Shadow Maps (CSM). This technique requires capturing multiple depth slices – the cascades to maintain enough resolution as we move further away from...

Improving ray-traced shadows

In the previous section, we described a simple algorithm that can be used to compute the visibility term in our scene. As we mentioned, this doesn’t scale well for a large number of lights and can require a large number of samples for different types of light.

In this section, we are going to implement a different algorithm inspired by the article Ray Traced Shadows in the Ray Tracing Gems book. As will be common in this chapter and upcoming chapters, the main idea is to spread the computation cost over time.

This can still lead to noisy results, as we are still using a low number of samples. To achieve the quality we are looking for, we are going to make use of spatial and temporal filtering, similar to what we did in Chapter 11, Temporal Anti-Aliasing.

The technique is implemented over three passes, and we are also going to leverage motion vectors. We are now going to explain each pass in detail.

Motion vectors

As we saw in Chapter...

Summary

In this chapter, we have presented two implementations for ray-traced shadows. In the first section, we provided a simple implementation similar to what you might find in an offline renderer. We simply shoot one ray per fragment to each light to determine whether it’s visible or not from that position.

While this works well for point lights, it would require many rays to support other light types and render soft shadows. For this reason, we also provided an alternative that makes use of spatial and temporal information to determine how many samples to use per light.

We start by computing the visibility variance of the past four frames. We then filter this value to determine how many rays to shoot for each fragment for each light. We use this count to traverse the scene and determine the visibility value for each fragment. Finally, we filter the visibility we obtained to reduce the noise. The filtered visibility is then used in the lighting computation to determine...

Further reading

The technique we have implemented in this chapter is detailed in Chapter 13, Revisiting Shadows with Ray Tracing, of the book Ray Tracing Gems. It is freely available here: http://www.realtimerendering.com/raytracinggems/rtg/index.html.

We have only used a limited set of the GLSL APIs available for ray tracing. We recommend reading the GLSL extension specification to see all the options available:

We used a few filters in this chapter. Signal processing is a vast and wonderful field that has more implications in graphics programming than people realize. To get you started, we recommend this article by Bart Wronski: https://bartwronski.com/2021/02/15/bilinear-down-upsampling-pixel-grids-and-that-half-pixel-offset/.

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Mastering Graphics Programming with Vulkan
Published in: Feb 2023Publisher: PacktISBN-13: 9781803244792
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Authors (2)

author image
Marco Castorina

Marco Castorina first got familiar with Vulkan while working as a driver developer at Samsung. Later he developed a 2D and 3D renderer in Vulkan from scratch for a leading media-server company. He recently joined the games graphics performance team at AMD. In his spare time, he keeps up to date with the latest techniques in real-time graphics.
Read more about Marco Castorina

author image
Gabriel Sassone

Gabriel Sassone is a rendering enthusiast currently working as a Principal Rendering Engineer at Multiplayer Group. Previously working for Avalanche Studios, where his first contact with Vulkan happened, where they developed the Vulkan layer for the proprietary Apex Engine and its Google Stadia Port. He previously worked at ReadyAtDawn, Codemasters, FrameStudios, and some non-gaming tech companies. His spare time is filled with music and rendering, gaming, and outdoor activities.
Read more about Gabriel Sassone