top of page
Poster_edited.jpg

Real-time Ray-traced Caustics

Overview

For my master's thesis, I performed research on using screen space photon mapping with DXR framework to generate dynamic caustics on glassware and water while maintaining performance to allow for real-time rendering.

Project Details

  • Role: Graphics Programmer

  • Engine: Venus Engine

  • Language: C++, HLSL 6.0

  • Development Time: 7 months​

SSPM

Screen Space Photon Mapping

The fundamental concept behind caustics rendering is calculating the contribution of photon. Caustics are visible when photons concentrating on an opaque surface. 

To simulate the caustics effect, I use the screen space photon mapping (SSPM), introduced by Hyuk Kim [1], instead of traditional algorithm. The algorithm use screen space buffer to store photons from light camera view, and sample the photon buffer by view vector, which is same as shadow mapping. The main purpose of this is to:

  • Guarantee the real-time performance.​

  • Use DXR api function to generate photon rays.

Below flowchart illustrate the process of screen space photon mapping.

ScreenSpacePhotonMapping.drawio.png

When updating the photon info that hit on translucent material, radiances as energy would be attenuated, and the new direction is calculated by these rules:

  • Reflected vector: RayDirection - 2 * DotProduct(RayDirection, SurfaceNormal) * SurfaceNormal

  • Refracted vector: Snell's law

Reflective and refraction factor determines the contribution of new photon rays.

Reflected and refracted ray direction

Radiance of photons could be color, or the coefficient of color enhancement. Below image is the visualization using red channel.

PhotonBuffer.png
GaussBlur

Gaussian Blur

As the image above shows the SSPM, photon buffer is filled with noise. Since most of the noise are low-pass, so I implement the gaussian filtering in compute shader to denoise the buffer. Here's the code:

Gaussian Blur CS

After denoising, the quality of photon buffer is improved.

GaussianBlur.png
StaticObjectsCaustics

Static Object Caustics

SSPM is a 2-Pass algorithm. After photon mapping pass, the ray-traced pass performs to shade the scene with specific lighting model. The basic concept of caustics shading is the additive blending, or the enhancement of shaded color. Below source codes are the raytracing shaders used in static glassware rendering.

Raytraced shading

Translucent effect and shadow are calculated in this pass. User can set a higher bouncing limitation to get a better effect, but it would reduce the performance extremely.

In the first scene, I put several glassware (5 cups with 1 upside down, and 1 ring), at the center of an opaque plane with ground texture. Light source is 1 spot light or 1 directional light. The performance of 2-Pass raytracing (limited in 3 bounces) of this scene is stable 60 fps.

Poster_edited.jpg

The quality of photon mapping is determined by resolution. Higher the resolution, more accurate the caustics. Here's the comparison among 512 x 512, 1024 x 1024 and 2048 x 2048.

CausticsStaticGlassware512.gif

512 x 512

CausticsStaticGlassware1024.gif

1024 x 1024

CausticsStaticGlassware2048.gif

2048 x 2048

GerstnerWaveFunction
WaterCaustics

Gerstner Wave Function

In fluid dynamics, Gerstner wave is an exact solution of the Euler equations for periodic surface gravity waves [2]. I implement this method to generate the water wave for caustics. In application, there're 8 random wave coefficients to synthesize the final wave and it allow user to reset by debug key. Below vertex shader is the implementation of this method.

Gerstner Wave Function VS

There's one issue in here. The normal calculated in vertex shader is incorrect. To solve this issue, I recalculate the normal in the pixel shader by using hlsl intrinsic function ddx() and ddy().

Since the vertex data of water would be changed in every frame, the bottom level acceleration structure of water should also rebuild correspondingly.

GerstnerWave.gif

Water Caustics

Water caustics rendering is more complex than static objects because the acceleration structure is updated in every frame. In order to shorten the calculation time, we limit the number of bouncing to 1, and start the photon mapping from water vertex position instead of light camera view. This is based on the algorithm invented by Holger Gruen [3].

To get the water position and normal, we render the water in the light camera view, and use Multiple Render Targets (MRT) in pixel shader to output the information.

MRT pixel shader

Below images shows the water position (RGB), normal and depth (RGB for normal, A for depth).

WaterPositionRT.png

Water position buffer

WaterNormalRT.jpg

Water normal and depth buffer

The output is not only the radiance of photon, but the hit position and the radiance (RGB for position, A for radiance). After that, we accumulate the photon to player screen by using compute shader.

Photon accumulation CS

In the end, we get the caustics output of dynamic water.

CausticsMovableWater.gif
Reference

References

  1. Kim, Hyuk. (2019). Caustics Using Screen-Space Photon Mapping: High-Quality and Real-Time Rendering with DXR and Other APIs. 10.1007/978-1-4842-4427-2_30. 

  2. Wikipedia contributors. (2021, July 1). Trochoidal wave. In Wikipedia, The Free Encyclopedia. Retrieved 21:08, March 19, 2022, from https://en.wikipedia.org/w/index.php?title=Trochoidal_wave&oldid=1031477851

  3. Gruen, Holger. "Ray-guided volumetric water caustics in single scattering media with dxr." Ray Tracing Gems. Apress, Berkeley, CA, 2019. 183-201.

bottom of page