Implemented Path tracing using Direct3D 12 and DirectX Raytraycing (DXR)
Used Lambert diffuse BRDF, and microfacet model for specular BRDF physcially based rendering (PBR) techniques for both direct and indirect light transport
Implemented spatiotemporal reservoir sampling (ReSTIR) for sampling lights during the direct lighting phase in multiple light scenarios to gain a performance boost while retaining the visual quality compared to other importance sampling techniques.
As of now, "Sponza" scene can be rendered with 110 lights by sampling 32 lights per pixel, obtaining a stable 120+ fps with a low-noise render.
Pipeline Overview
Reservoir structure stores 4 different pieces of information for every pixel
Number of lights sampled to shade this pixel in the current frame
The some of MIS weights of the lights sampled
The index of the light that is contributing the most to this pixel's color
The probabilistic weight of the most important light
Each pixel stores 3 different reservoir structures:
Reservoir from previous frame
Reservoir from current frame after temporal reuse
Reservoir from current after both temporal and spatial reuse
The rendering pipeline involves 3 different phases
Pass 1: GBuffer and Temporal Updated Reservoir Pass (Temporal Reuse)
Pass 2: Spatial Reuse
Pass 3: Direct and Indirect lighting
The first pass involves shooting rays and at each hit point store the hit positions, shading normals, geometry normals, and material data into different render textures that I can use in the subsequent steps and passes.
Then I calculate motion vectors by taking the hit position in screen space from the current frame and previous frame.
Next, I create a reservoir for each pixel. I choose 32 out of 110 lights in the scene at random, evaluate weights for all of these lights dividing the contribution with the pdf and only choose the ones with a positive non zero weight.
Finally, I get the pixel's previous reservoir with the help of motion vectors and update the current frame reservoir with the last frame's reservoir.
For each pixel, I choose 5 pixels at a 30 pixel radius and update the pixel's reservoir with each pixel's temporal updated reservoir, finishing off spatial reuse.
For each pixel, I choose every pixel in a 30 pixel radius and update the pixel's reservoir with each pixel's temporal updated reservoir, finishing off spatial reuse.