Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 152 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,159 @@
CUDA Denoiser For CUDA Path Tracer
==================================
================

**University of Pennsylvania, CIS 565: GPU Programming and Architecture, Project 4**

* (TODO) YOUR NAME HERE
* Tested on: (TODO) Windows 22, i7-2222 @ 2.22GHz 22GB, GTX 222 222MB (Moore 2222 Lab)
* Xiaoyue Ma
* [LinkedIn](https://www.linkedin.com/in/xiaoyue-ma-6b268b193/)
* Tested on: Windows 10, i7-12700H @ 2.30 GHz 16GB, GTX3060 8GB

### (TODO: Your README)
# Overview
This project implements a CUDA-powered pathtracing denoiser that utilizes geometry buffers (G-buffers) to steer a smoothing filter. Drawing inspiration from the study "[Edge-Avoiding A-Trous Wavelet Transform for Fast Global Illumination Filtering](https://jo.dreggn.org/home/2010_atrous.pdf)", this denoiser enhances the appearance of pathtraced images by producing smoother results with fewer samples per pixel.

*DO NOT* leave the README to the last minute! It is a crucial part of the
project, and we will not be able to grade you without a good README.
<p align="center">
<img width="800" height="280" src="img/alg.png" alt="Intro">
</p>

By iteratively applying sparse blurs of increasing sizes, one can approximate the effects of a Gaussian filter. Instead of using a large filter, this method utilizes a smaller one but spaces out the samples that pass through it. Interestingly, to achieve a greater blur size, it doesn't require enlarging the filter; instead, it demands more iterations. This approach optimizes performance while still achieving the desired blurring effect.

<p align="center">
<img width="800" height="200" src="img/alg2.png" alt="Intro">
</p>

# Features
## Core features
##### **A-Trous**

A-Trous Filtering enhances our denoiser's efficiency by applying iterative sparse blurs, achieving large filter results with a smaller filter size.

|No Filter | Filter Size = 16 | Filter Size = 64 |
|:-----: | :-----: |:-----: |
|![](img/10ori.png) | ![](img/10GnoEdge16.png) | ![](img/10AnoEdge64.png) |

##### **Edge-Avoiding A-Trous**

A-Trous Filtering can blur vital details, but using G-buffer information, we adjust blurring on sharp edges to preserve key image elements, optimizing denoising.

|No Filter | A-Trous (64) | A-Trous with Edge-Avoiding (64) |
|:-----: | :-----: |:-----: |
|![](img/10ori.png) | ![](img/10AnoEdge64.png) | ![](img/10AEdge64.png) |

##### **G-Buffer**

Using normal, position, and time intersection data as weights, we minimize edge blurring during application. This data is viewable via the "Show GBuffer" option in the GUI.

| Time to Intersect |Normal | Position |
|:-----: | :-----: |:-----: |
|![](img/time.png) | ![](img/pos.png) | ![](img/nor.png) |

## Extra Feature

#### Gaussian Filtering


The Gaussian Filter calculates a pixel's new color by averaging its neighbors, giving more weight to those nearby. In my tests, it generated a more blurred image when edge-avoiding was off and a marginally noisy one when on.

|No Filter | A-Trous (16) | Gaussian (16)|
|:-----: | :-----: |:-----: |
|![](img/10ori.png) | ![](img/10AnoEdge16.png) | ![](img/10GnoEdge16.png) |


| A-Trous Edge-Avoiding(64) | Gaussian Edge-Avoiding(64)|
|:-----: | :-----:|
![](img/10AEdge64.png) | ![](img/10GEdge64.png) |



# Performance Analysis

### **How much time denoising adds to the renders**

The denoiser activates after the path tracer's image rendering, with its runtime being influenced by image resolution and filter size, not scene complexity. My tests show that for an 800x800 image with an 80x80 filter, the denoising time remains consistent regardless of iteration count.

<p align="center">
<img width="800" height="400" src="img/chart1.png" alt="Chart">
</p>


### **How denoising influences the number of iterations needed to get an "acceptably smooth" result**

Perceptions of "smoothness" differ among individuals and can be influenced by various image factors. In the **'cornell_ceiling_light'** test, a smooth appearance was achieved at 300 iterations without denoising. With denoising, only 150 iterations were needed, marking a 100% reduction. While the benefit of denoising can depend on the scene, it notably reduces required iterations overall.

No Denoising, 300 iterations | Denoised, 150 iterations
:----------:|:-----------:
![](img/300ori.png) | ![](img/150de.png)

### **How denoising at different resolutions impacts runtime**

The runtime for denoising rises with resolution, but the increase isn't linear. For instance, even though a significant resolution jump (from 200x200 to 800x800) is made, the runtime only multiplies by seven. As the resolution increases, the denoising process requires more time, attributed to the higher pixel count and added A-trous filter iterations. However, this growth in runtime doesn't scale proportionally with the resolution.

<p align="center">
<img width="800" height="500" src="img/chart2.png" alt="Chart">
</p>


### **How varying filter sizes affect performance**

Predictably, an increase in filter size results in an extended denoising runtime because more neighboring pixels get sampled to determine each pixel's new color. In a chart derived from the test at an 800x800 resolution, while there's a relationship between additional time and filter size, it's not strictly linear.

<p align="center">
<img width="800" height="500" src="img/chart3.png" alt="Chart">
</p>

### **How visual results vary with filter size -- does the visual quality scale uniformly with filter size?**

For images from the test scene at 10 iteration, denoising sees a marked improvement from 32 to 64 and a discernible one from 16 to 32. However, further increments offer limited visual benefits.

Filter Size 4 | Filter Size 16 | Filter Size 32 | Filter Size 64 |
:-----:|:-----:|:-----:|:-----:|
![](img/10AEdge4.png) | ![](img/10AEdge16.png) | ![](img/10AEdge32.png) | ![](img/10AEdge64.png) |

### **How effective/ineffective is this method with different material types**

This technique excels with diffuse materials, but often results in a softer appearance as the "roughness" diminishes from color smoothing. Its efficacy is diminished with reflections, causing them to blur noticeably and reducing the material's shine.

Diffuse | Specular | Imperfect Specular
:----------:|:-----------:|:-----------:
![](img/diffuse.png) | ![](img/10AEdge64.png) | ![](img/imperfact.png)


### **How do results compare across different scenes**
**For example, between `cornell.txt` and `cornell_ceiling_light.txt`. Does one scene produce better denoised results? Why or why not?**

The efficacy of denoising is scene-dependent. In the cornell_ceiling_light setup, it shows promising results, whereas in the standard cornell scene, it's less effective. Uniformly lit scenes with limited color variations favor denoisers, as consistent illumination aids in rapid light emission computations. In contrast, darker scenes with infrequent bright spots introduce more noise, posing challenges to the denoising process.

Cornell Scene | Light Cornell Scene
:----------:|:-----------:
![](img/10cornell.png) | ![](img/10AEdge64.png)


### **A-Trous Filtering vs. Gaussian Filtering**

In performance comparisons, A-Trous Filtering notably surpasses Gaussian Filtering. A-Trous runtime grows almost linearly with increasing filter size or resolution, whereas Gaussian's runtime rises exponentially.

<p align="center">
<img width="800" height="500" src="img/chart4.png" alt="Chart">
</p>

### Confuse

In this paper, the right implementation code is like:
```
glm::vec3 ntmp = gBuffer[idxtmp].nor;
t = nval - ntmp;
dist2 = glm::max((glm::dot(t, t) / (stepWidth * stepWidth)), 0.0f);
float n_w = glm::min(glm::exp(-dist2 / n_phi), 1.0f);
```

But I found that just applied
```
glm::vec3 ntmp = gBuffer[idxtmp].nor;
t = nval - ntmp;
dist2 = glm::dot(t, t);
float n_w = glm::min(glm::exp(-dist2 / n_phi), 1.0f);
```
will make the denoise effect better.

Original Version | Simple Code Version
:----------:|:-----------:
![](img/10AEdge16.png) | ![](img/10AEdge16extra.png)
Binary file added img/10AEdge16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/10AEdge16extra.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/10AEdge32.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/10AEdge4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/10AEdge64.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/10AnoEdge16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/10AnoEdge32.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/10AnoEdge64.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/10GEdge64.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/10GnoEdge16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/10cornell.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/10cornell1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/10ori.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/150de.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/300ori.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/alg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/alg2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/chart1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/chart2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/chart3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/chart4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/diffuse.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/imperfact.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/nor.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/pos.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/time.png
20 changes: 19 additions & 1 deletion scenes/cornell.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,29 @@ REFR 0
REFRIOR 0
EMITTANCE 0

MATERIAL 5
RGB .527 .804 .976
SPECEX 0
SPECRGB .98 .98 .98
REFL 0
REFR 0
REFRIOR 0.71
EMITTANCE 0

MATERIAL 6
RGB .527 .804 .976
SPECEX 0
SPECRGB .98 .98 .98
REFL 1
REFR 1
REFRIOR 1.33
EMITTANCE 0

// Camera
CAMERA
RES 800 800
FOVY 45
ITERATIONS 5000
ITERATIONS 10
DEPTH 8
FILE cornell
EYE 0.0 5 10.5
Expand Down
18 changes: 18 additions & 0 deletions scenes/cornell_ceiling_light.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,24 @@ REFR 0
REFRIOR 0
EMITTANCE 0

MATERIAL 5
RGB .527 .804 .976
SPECEX 0
SPECRGB .98 .98 .98
REFL 0
REFR 0
REFRIOR 0.71
EMITTANCE 0

MATERIAL 6
RGB .527 .804 .976
SPECEX 0
SPECRGB .98 .98 .98
REFL 1
REFR 1
REFRIOR 1.33
EMITTANCE 0

// Camera
CAMERA
RES 800 800
Expand Down
Loading