Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Project 4 : Gizem Dal #13

Open
wants to merge 8 commits into
base: base-code
Choose a base branch
from
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
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,10 @@ source_group(Headers FILES ${headers})
source_group(Sources FILES ${sources})
source_group(imgui FILES ${imgui})

#add_subdirectory(stream_compaction) # TODO: uncomment if using your stream compaction
add_subdirectory(stream_compaction) # TODO: uncomment if using your stream compaction

cuda_add_executable(${CMAKE_PROJECT_NAME} ${sources} ${headers} ${imgui})
target_link_libraries(${CMAKE_PROJECT_NAME}
${LIBRARIES}
#stream_compaction # TODO: uncomment if using your stream compaction
stream_compaction # TODO: uncomment if using your stream compaction
)
100 changes: 95 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,101 @@ 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)
* Name: Gizem Dal
* [LinkedIn](https://www.linkedin.com/in/gizemdal), [personal website](https://www.gizemdal.com/)
* Tested on: Predator G3-571 Intel(R) Core(TM) i7-7700HQ CPU @ 2.80 GHz 2.81 GHz - Personal computer

### (TODO: Your README)
<img src="img/renders/readme_reg.png" alt="reg" width=400> <img src="img/renders/readme_denoised.png" alt="denoised" width=400>

*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.
*Iterations: 10, Filter Size: 10, Blur Size: 63, Color Weight: 38.008, Normal Weight: 0.407, Position Weight: 3.862*

## Project Description ##

This project focuses on implementing a pathtracing denoiser that uses geometry buffers (G-buffers) to guide a smoothing filter. The technique is based on the [Edge-Avoiding A-Trous Wavelet Transform for fast Global Illumination Filtering](https://jo.dreggn.org/home/2010_atrous.pdf) paper by Dammertz, Sewtz, Hanika, and Lensch.

**Features **

* GBuffer Visualization
* Position
* Normal
* Material base color
* Adjustable filter & blur size
* Guided denoiser

## GBuffer Visualization ##

GBuffers include scene geometry information such as per-pixel normals and per-pixel positions, as well as surface color for preserving detail in mapped or procedural textures. The current implementation stores per-pixel metrics only from the first bounce.

Position | Normal | Base Color
:---: | :---: | :---:
<img src="img/renders/gbuffer_pos.png" alt="pos" width=300> | <img src="img/renders/gbuffer_nor.png" alt="nor" width=300> | <img src="img/renders/gbuffer_col.png" alt="col" width=300>

## Denoising Parameters ##

Denoising parameters such as filter and blur sizes, number of iterations, color/normal/position weights are adjustable from the provided [Imgui](https://github.com/ocornut/imgui) GUI.

**Blur Size**

The examples below use the following other parameter values: *Filter Size = 5; Iter = 2; Col_W = 11.789; Nor_W = 0.610; Pos_W = 0.407*

Blur=10 | Blur=33 | Blur=80 | Blur=185
:---: | :---: | :---: | :---:
<img src="img/renders/blur_10.png" alt="pos" width=300> | <img src="img/renders/blur_33.png" alt="nor" width=300> | <img src="img/renders/blur_80.png" alt="col" width=300> | <img src="img/renders/blur_185.png" alt="col" width=300>

Increasing the blur size allows more denoiser iterations since the blur size determines the largest expansion width the filter can reach. Applying more iterations result in smoother images, especially for very small number of path tracer iterations (which in this example is only 2). However, increasing the blur size has performance implications as well (check the Performance Analysis section below).

**Color Weight**

The examples below use the following other parameter values: *Filter Size = 5; Iter = 2; Blur Size = 80; Nor_W = 0.610; Pos_W = 0.407*

Col_W=1.423 | Col_W=4.675 | Col_W=15.244 | Col_W=30.285
:---: | :---: | :---: | :---:
<img src="img/renders/col_1.423.png" alt="pos" width=300> | <img src="img/renders/col_4.675.png" alt="nor" width=300> | <img src="img/renders/col_15.244.png" alt="col" width=300> | <img src="img/renders/col_30.285.png" alt="col" width=300>

The results suggest that increasing the color weight results in smoother denoised results. Lower color weights result in denoised renders with more "fireflies" while larger weights give smoother results. However, it is important to mention that the impact of color weight may depend from implementation to implementation. The current adaptation from the A-Trous approach halves the color weight at each denoise blur iteration in order to smoothen smaller smaller illumination variations, as suggested by the paper.

**Light Size**

The examples below use the following other parameter values: *Filter Size = 5; Iter = 10; Blur Size = 63; Col_W = 28.455 Nor_W = 0.813; Pos_W = 3.862, Light intensity = 1*

Light Width = 3 | Light Width = 5 | Light Width = 7 | Light Width = 10
:---: | :---: | :---: | :---:
<img src="img/renders/3_light.png" alt="pos" width=300> | <img src="img/renders/5_light.png" alt="nor" width=300> | <img src="img/renders/7_light.png" alt="col" width=300> | <img src="img/renders/10_light.png" alt="col" width=300>

However, increasing the light intensity may result in less smoother results with a lot of fireflies. The example below use a light width of 3 and intensity of 5, keeping the other parameters constant.

<img src="img/renders/3_light_5_50.png" alt="pos" width=300>

**Filter Size**

For the purpose of analyzing the effect of different sizes, I implemented the denoiser filter size to be adjustable rather than set to 5 as constant. The examples below use the following parameters: *Col_W = 16.667 Nor_W = 0.610; Pos_W = 0.813* The blur sizes are adjusted to allow the same number of blur iterations for different filter sizes.

Filter = 5, Blur = 80 | Filter = 9, Blur = 80 | Filter = 21, Blur = 81 | Filter = 43, Blur = 103
:---: | :---: | :---: | :---:
<img src="img/renders/filter_5.png" alt="pos" width=300> | <img src="img/renders/filter_9.png" alt="nor" width=300> | <img src="img/renders/filter_21_81.png" alt="col" width=300> | <img src="img/renders/filter_43_103.png" alt="col" width=300>

The results suggest that changing the filter size doesn't seem to have a significant impact on denoiser results.

## Performance Analysis ##

I used a GPU timer to conduct my performance analysis on different settings in the denoiser. This timer is wrapped up as a performance timer class, which uses the CUDAEvent library, in order to measure the time cost conveniently. The timer is started right before the denoiser computation and is terminated once it ends. The measured time excludes memory operations such as cudaMalloc() and cudaMemset().

Measured runtimes are noted in miliseconds.

**Material Type**

Diffuse | Specular | Glossy | Fresnel
:---: | :---: | :---: | :---:
23.068 | 23.1178 | 23.0083 | 22.999

**Filter Size**

5 | 9 | 21 | 43
:---: | :---: | :---: | :---:
23.1178 | 73.1147 | 323.145 | 1343.26

**Blur Size**

16 | 33 | 80 | 173
:---: | :---: | :---: | :---:
9.5744 | 18.6659 | 23.1178 | 27.8777
Binary file added img/renders/10_light.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/renders/10_light1.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/renders/3_light.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/renders/3_light1.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/renders/3_light_5.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/renders/3_light_5_50.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/renders/5_light.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/renders/5_light1.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/renders/7_light.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/renders/7_light1.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/renders/7_light_5.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/renders/7_light_5_50.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/renders/blur_10.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/renders/blur_185.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/renders/blur_33.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/renders/blur_80.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/renders/col_1.423.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/renders/col_15.244.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/renders/col_30.285.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/renders/col_38.415.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/renders/col_4.675.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/renders/filter_21.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/renders/filter_21_81.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/renders/filter_43.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/renders/filter_43_103.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/renders/filter_5.png
Binary file added img/renders/filter_9.png
Binary file added img/renders/gbuffer_col.png
Binary file added img/renders/gbuffer_nor.png
Binary file added img/renders/gbuffer_pos.png
Binary file added img/renders/iter_2.png
Binary file added img/renders/iter_2_denoised_16.png
Binary file added img/renders/iter_2_denoised_61.png
Binary file added img/renders/iter_2_denoised_79.png
Binary file added img/renders/iter_2_final.png
Binary file added img/renders/iter_3_final.png
Binary file added img/renders/iter_9_final.png
Binary file added img/renders/no_blur.png
Binary file added img/renders/readme_denoised.png
Binary file added img/renders/readme_reg.png
12 changes: 6 additions & 6 deletions scenes/cornell.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ SPECRGB 0 0 0
REFL 0
REFR 0
REFRIOR 0
EMITTANCE 5
EMITTANCE 1

// Diffuse white
MATERIAL 1
Expand Down Expand Up @@ -43,16 +43,16 @@ MATERIAL 4
RGB .98 .98 .98
SPECEX 0
SPECRGB .98 .98 .98
REFL 1
REFR 0
REFRIOR 0
REFL 0
REFR 1
REFRIOR 2.5
EMITTANCE 0

// Camera
CAMERA
RES 800 800
FOVY 45
ITERATIONS 5000
ITERATIONS 2
DEPTH 8
FILE cornell
EYE 0.0 5 10.5
Expand All @@ -66,7 +66,7 @@ cube
material 0
TRANS 0 10 0
ROTAT 0 0 0
SCALE 3 .3 3
SCALE 10 .3 10

// Floor
OBJECT 1
Expand Down
76 changes: 65 additions & 11 deletions scenes/cornell_ceiling_light.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,24 +38,54 @@ REFR 0
REFRIOR 0
EMITTANCE 0

// Specular white
// Specular blue
MATERIAL 4
RGB .98 .98 .98
RGB .65 .65 .98
SPECEX 0
SPECRGB .65 .65 .98
REFL 1
REFR 0
REFRIOR 0
EMITTANCE 0

// Fresnel magenta
MATERIAL 5
RGB .98 .65 .98
SPECEX 0
SPECRGB .98 .98 .98
SPECRGB .98 .65 .98
REFL 0
REFR 1
REFRIOR 2.5
EMITTANCE 0

// Glossy cyan
MATERIAL 6
RGB .65 .98 .98
SPECEX 7.5
SPECRGB .65 .98 .98
REFL 1
REFR 0
REFRIOR 0
EMITTANCE 0

// Diffuse yellow
MATERIAL 7
RGB .98 .98 .65
SPECEX 0
SPECRGB .98 .98 .65
REFL 0
REFR 0
REFRIOR 0
EMITTANCE 0

// Camera
CAMERA
RES 800 800
FOVY 45
ITERATIONS 10
DEPTH 8
FILE cornell
EYE 0.0 5 10.5
EYE 0.0 5 9.5
LOOKAT 0 5 0
UP 0 1 0

Expand All @@ -66,15 +96,15 @@ cube
material 0
TRANS 0 10 0
ROTAT 0 0 0
SCALE 10 .3 10
SCALE 20 .3 10

// Floor
OBJECT 1
cube
material 1
TRANS 0 0 0
ROTAT 0 0 0
SCALE 10 .01 10
SCALE 20 .01 10

// Ceiling
OBJECT 2
Expand All @@ -90,28 +120,52 @@ cube
material 1
TRANS 0 5 -5
ROTAT 0 90 0
SCALE .01 10 10
SCALE .01 10 20

// Left wall
OBJECT 4
cube
material 2
TRANS -5 5 0
TRANS -10 5 0
ROTAT 0 0 0
SCALE .01 10 10

// Right wall
OBJECT 5
cube
material 3
TRANS 5 5 0
TRANS 10 5 0
ROTAT 0 0 0
SCALE .01 10 10

// Sphere
// Mirror Sphere
OBJECT 6
sphere
material 4
TRANS -1 4 -1
TRANS -7.5 4 -2
ROTAT 0 0 0
SCALE 3 3 3

// Diffuse Sphere
OBJECT 7
sphere
material 7
TRANS -2.5 4 -2
ROTAT 0 0 0
SCALE 3 3 3

// Fresnel Sphere
OBJECT 8
sphere
material 5
TRANS 2.5 4 -2
ROTAT 0 0 0
SCALE 3 3 3

// Glossy Sphere
OBJECT 9
sphere
material 6
TRANS 7.5 4 -2
ROTAT 0 0 0
SCALE 3 3 3
69 changes: 66 additions & 3 deletions src/interactions.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,36 @@ glm::vec3 calculateRandomDirectionInHemisphere(
+ sin(around) * over * perpendicularDirection2;
}

/*
* Computes sampled glossy reflection direction.
*/
__host__ __device__
glm::vec3 calculateImperfectSpecularDirection(
glm::vec3 normal, float spec_exp, thrust::default_random_engine& rng) {
thrust::uniform_real_distribution<float> u01(0, 1);
float theta = glm::acos(glm::pow(u01(rng), 1.f / (spec_exp + 1.f)));
float phi = TWO_PI * u01(rng);
glm::vec3 sample_dir(cos(phi) * sin(theta), sin(phi) * sin(theta), cos(theta));

// Compute tangent space
glm::vec3 tangent;
glm::vec3 bitangent;

if (glm::abs(normal.x) > glm::abs(normal.y)) {
tangent = glm::vec3(-normal.z, 0.f, normal.x) / glm::sqrt(normal.x * normal.x + normal.z * normal.z);
}
else {
tangent = glm::vec3(0, normal.z, -normal.y) / glm::vec3(normal.y * normal.y + normal.z * normal.z);
}
bitangent = glm::cross(normal, tangent);

// Transform sample from specular space to tangent space
glm::mat3 transform(tangent, bitangent, normal);
return glm::normalize(transform * sample_dir);
}

/**
* Simple ray scattering with diffuse and perfect specular support.
* Simple ray scattering with diffuse, perfect specular, glossy and fresnel dielectric support.
*/
__host__ __device__
void scatterRay(
Expand All @@ -52,8 +80,43 @@ void scatterRay(
thrust::default_random_engine &rng) {
glm::vec3 newDirection;
if (m.hasReflective) {
newDirection = glm::reflect(pathSegment.ray.direction, normal);
} else {
if (m.specular.exponent > 0.f) {
// Glossy
newDirection = calculateImperfectSpecularDirection(normal, m.specular.exponent, rng);
}
else {
// Mirror
newDirection = glm::reflect(pathSegment.ray.direction, normal);
}
}
else if (m.hasRefractive) {
// Fresnel
float cosine;
float reflect_prob;
bool entering = glm::dot(pathSegment.ray.direction, normal) < 0;
float etaI = entering ? 1.f : m.indexOfRefraction;
float etaT = entering ? m.indexOfRefraction : 1.f;
float eta = etaI / etaT;
cosine = entering ? -glm::dot(pathSegment.ray.direction, normal) / glm::length(pathSegment.ray.direction) :
m.indexOfRefraction * glm::dot(pathSegment.ray.direction, normal) / glm::length(pathSegment.ray.direction);
newDirection = glm::refract(pathSegment.ray.direction, normal, eta);
if (glm::length(newDirection) == 0.f) {
reflect_prob = 1.f;
}
else {
float R0 = (etaI - etaT) / (etaI + etaT);
R0 *= R0;
reflect_prob = R0 + (1.f - R0) * glm::pow(1.f - cosine, 5.f);
}

thrust::uniform_real_distribution<float> u01(0, 1);
float prob = u01(rng);
if (prob < reflect_prob) {
newDirection = glm::reflect(pathSegment.ray.direction, normal);
}
}
else {
// Diffuse
newDirection = calculateRandomDirectionInHemisphere(normal, rng);
}

Expand Down
Loading