GLOBAL ILLUMINATION
Per Pixel global illumination using Spatiotemporal Variance-Guided filtering.
Goals
The goal of this project was to understand how global illumination is achieved in real time in games. and implement it in my personal engine. Existing methods employ screen space GI or Irradiance probes to calculate an estimation of global illumination at specific points. During my research, I came across how unreal engine achieves GI in lumen using Voxel based cone tracing. Further research led me to choose Raytraced Global Illumination using Spatiotemporal Variance-Guided Filtering as my solution.
Rendering Pipeline
Overview of the pipeline :
-
The initial raytracer pass gives the G Buffers like albedo, normals and depth. It also calculates a motion vector which will be used in later stages.
-
The second raytacer GI pass calculates luminance at a pixel level by using cosine weighted sampling. This noisy GI output is then denoised using SVGF.
-
The GI Buffer is temporally reprojected using the motion vector to get more samples.
-
The output of the temporal sampler is then run across a variance estimator and an À-Trous wavelet filter to get the final denoised image.
Deferred Rendering
The initial Raytracer pass uses DXR to traverse acceleration structures and gives the base GBuffers like normal, albedo, depth and velocity. The velocity buffer is calculated by storing the previous frame view matrix and back projecting current frame data to previous frame.
Depth
World positions
Normals
Albedo
The GI Raytracer Pass
The GI pass then makes use of the initial G Buffers to do cosine-weighted sampling. This gives us the noisy GI buffer output. The radiance estimation also takes into account point lights like glowstone and torches.
GI Off
GI On
Temporal Reprojection and Variance Estimation
Temporal reprojection is then implemented as the first part of Spatiotemporal Variance-Guided filtering. It takes into account the velocity buffer(motion vector) and calculates irradiance values from previous frames and blends them into the current frame using a history buffer.
Temporal Sampler
Variance Estimation
Motion Vector
À-Trous Wavelet Filter
The À-Trous Wavelet filter is then run in iterations with each iteration taking more spatial pixels into account for denoising. In each stage the variance output is also updated in order to get a final noise free GBuffer.
Denoiser Off
Denoiser On
Crepuscular Rays
Crepuscular Rays or god rays is a screen space volumetric scattering technique used to simulate light rays from a large source like the sun. It is based on this article from Nvidia on how to achieve this using screen space techniques.
RETROSPECTIVE
What went well?
-
Implemented a global illumination solution from scratch.
-
Added Raytracing to the game engine.
-
Implemented deferred rendering with multiple render passes.
-
Added denoising support with specific inputs and outputs.
What went wrong?
-
Underestimated time taken to debug specific scenarios.
-
Looking back I would have started simple with a less complicated game and just focused on global illumination.
-
Didn't make time to build more worlds with specific materials.
What I learned?
-
How to research and implement a real time simulation technique with little guidance.
-
Understand how real time global illumination principles work.
-
Learnt the DX12 DX Raytracing API.
-
Understood how spatial and adaptive filters work in raytracing.