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

Project4: Jiyu Huang #4

Open
wants to merge 32 commits into
base: base-code
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
8421472
Remove unused freeglut copyrights
shehzan10 Jan 16, 2021
a79ca55
Update CUDA Computes List
shehzan10 Sep 10, 2021
78e028a
Retab
shehzan10 Sep 10, 2021
c03780d
Update instructions for Fall 2021
shehzan10 Sep 18, 2021
80ad206
Add vulkan option
shehzan10 Sep 18, 2021
cc3da39
Add sample readmes for inspiration
shehzan10 Sep 19, 2021
784f5ca
Merge pull request #1 from CIS565-Fall-2021/update-instructions-2021
shehzan10 Sep 21, 2021
c22abd9
adds shadeBSDF function
JiyuHuang Sep 29, 2021
0b5123d
implements scatterRay for diffuse
JiyuHuang Sep 29, 2021
132c03a
core features and mesh loading finished
JiyuHuang Oct 4, 2021
08a3f8b
implemented texture mapping, bump mapping and depth-of-field
JiyuHuang Oct 6, 2021
373b043
implements refraction
JiyuHuang Oct 6, 2021
1fde1b9
implemented anti-aliasing
JiyuHuang Oct 6, 2021
b8feb35
code cleanup
JiyuHuang Oct 6, 2021
fc18dfa
performance analysis
JiyuHuang Oct 8, 2021
403674a
readme update
JiyuHuang Oct 10, 2021
2660359
readme update
JiyuHuang Oct 10, 2021
e05893d
readme update
JiyuHuang Oct 10, 2021
c9f4daa
readme update
JiyuHuang Oct 10, 2021
d93ced3
readme update
JiyuHuang Oct 10, 2021
288a382
readme update
JiyuHuang Oct 10, 2021
b2e805a
readme update
JiyuHuang Oct 10, 2021
00fd5c7
readme update
JiyuHuang Oct 10, 2021
2da01b4
readme update: sources for models
JiyuHuang Oct 10, 2021
fe89489
add imgui and set up basic sliders for denoising parameters
JiyuHuang Oct 19, 2021
4d01bd3
add iterations slider and save-and-exit button to UI
JiyuHuang Oct 19, 2021
ca38a2c
visualization code for a gbuffer with dummy data as time-to-intersection
JiyuHuang Oct 19, 2021
78023c5
implementing a-trous filter
JiyuHuang Oct 20, 2021
48923b6
implementing a-trous filter
JiyuHuang Oct 21, 2021
892e26b
denoise and gbuffer optimization implemented
JiyuHuang Oct 21, 2021
365ee6a
analysis update
JiyuHuang Oct 21, 2021
f3346c2
gaussian blur compared
JiyuHuang Oct 21, 2021
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
24 changes: 21 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,34 @@ set(sources
src/utilities.cpp
)

set(imgui
imgui/imconfig.h
imgui/imgui.cpp
imgui/imgui.h
imgui/imgui_draw.cpp
imgui/imgui_internal.h
imgui/imgui_widgets.cpp
imgui/imgui_demo.cpp
imgui/imgui_impl_glfw.cpp
imgui/imgui_impl_glfw.h
imgui/imgui_impl_opengl2.cpp
imgui/imgui_impl_opengl2.h
imgui/imgui_impl_opengl3.cpp
imgui/imgui_impl_opengl3.h
)

list(SORT headers)
list(SORT sources)
list(SORT imgui)

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})
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
)
176 changes: 84 additions & 92 deletions INSTRUCTION.md

Large diffs are not rendered by default.

94 changes: 87 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,93 @@
CUDA Path Tracer
CUDA Denoiser For CUDA Path Tracer
================

**University of Pennsylvania, CIS 565: GPU Programming and Architecture, Project 3**
**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)
* Jiyu Huang
* Tested on: Windows 10, AMD Ryzen 7 5800H @ 3.20GHz 16GB, RTX 3070 Laptop 8GB

### (TODO: Your README)
| 10 iterations, no denoising | 10 iterations, denoised |
| --------------------------- | ----------------------- |
| ![](img/no-denoise.png) | ![](img/denoised.png) |

*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.
This project builds on top of the [CUDA path tracer](https://github.com/JiyuHuang/Project3-CUDA-Path-Tracer) project, and implements an edge-avoiding A-Trous wavelet transform for image denoising. The technique is described in detail in https://jo.dreggn.org/home/2010_atrous.pdf.

# Analysis

The default scene used for performance analysis can be found at [scenes/cornell_ceiling_light.txt](scenes/cornell_ceiling_light.txt), with a camera resolution of 800x800. The optimal block size chosen for A-Trous filter CUDA kernel is 32x32. The default filter size chosen is 65.

## Denoising Time vs Path-Tracing Time

Path-tracing and denoising times and measured by taking the average of ten executions. Ten iterations are performed in each execution. As seen from below, denoising using A-Trous wavelet transform takes relatively little amount of time compared to one iteration of path-tracing. When performed after several iterations of path-tracing, A-Trous denoising takes almost no overhead.

![](img/chart-pathtrace-denoise.png)

## Image Comparison

| no denoising, 10 iterations | no denoising, 40 iterations | no denoising, 100 iterations |
| ----------------------- | ---------------------------- | ----------------------------- |
| ![](img/no-denoise.png) | ![](img/cornell-40samp.png) |![](img/cornell-100samp.png) |

| denoised, 1 iteration | denoised, 4 iterations | denoised, 10 iterations |
| ----------------------- | ---------------------------- | ----------------------------- |
| ![](img/denoised-1samp.png) | ![](img/denoised-4samp.png) |![](img/denoised.png) |

As seen from the tables, it takes roughly 100 iterations to get a smooth image without denoising, and even after 100 iterations, the result image still has noise if looked closely. To get cleaner image, the iteration number increases quadratically.

On the other hand, a denoised image looks smooth even with only one iteration, with the catch being that the image has color blob artifacts. At 10 iterations, the artifacts get reduced and the result is an acceptably smooth image.

## Camera Resolution and Denoising Time

The relationship between camera resolution and denoising time is as expected: run time increases as screen size (n x n) increases.

![](img/chart-resolution.png)

## Filter Size and Denoising Time

Denoising time increases logarithmically as filter size increases. This is due to the fact that for the A-Trous wavelet transform, in each level the step width multiplies by 2. Therefore, the number of levels for the wavelet transform increases logarithmically.

![](img/chart-filtersize.png)

## Filter Size and Image Quality

| filter size: 5 | filter size: 9 | filter size: 17 |
| ------------------------ | ------------------------- | -------------------------- |
|![](img/filtersize-5.png) | ![](img/filtersize-9.png) | ![](img/filtersize-17.png) |

| filter size: 33 | filter size: 65 | filter size: 129 |
| -------------------------- | --------------------- | --------------------------- |
| ![](img/filtersize-33.png) | ![](img/denoised.png) | ![](img/filtersize-129.png) |

Increaing filter size improves image quality, but the quality benefit gets smaller as filter size increases.

## Limitation: Reflective/Refractive Materials, Uneven Lighting

The edge-avoiding A-Trous filter uses position and normal information in its G-buffer to avoid blurring edges. For reflective or refractive materials, the filter can't effectively detect the edges in the reflection/refraction, and will blur the surfaces with those materials.

| no denoising | denoised |
| --------------------------- | ----------------------- |
| ![](img/sharp.png) | ![](img/blur.png) |

For similar reasons, when the lighting condition isn't very even, the image result will also suffer.

| 10 iterations, even lighting condition | 10 iterations, not so even lighting condition |
| ----------------------- | --------------- |
| ![](img/denoised.png) | ![](img/cornell-denoised.png) |

## G-Buffer Optimization and Performance

To more efficiently store G-buffer information, we use z-depths and oct-encoded normals instead of positions and normals. There seems to be no apparent performance impact for this optimization. The difference seen in the graph is more of a result of performance time variance rather than any meaningful performance difference.

![](img/chart-gbuffer.png)

## Edge-Avoiding A-Trous Wavelet Transform vs Gaussian Blur

Compared to our implementation, Gaussian blur doesn't get rid of noise so much as to smooth out the noise, with the additional downside of blurring the entire image.

| filter size: 65, A-Trous | filter size: 65, Gaussian | reference |
| --------------------------- | ----------------------- | -- |
| ![](img/denoised.png) | ![](img/gaussian.png) | ![](img/no-denoise.png) |

Performance wise, Gaussian blur is also getting expensive as the filter size increases.

![](img/chart-gaussian.png)
8 changes: 5 additions & 3 deletions cmake/CUDAComputesList.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ IF( CUDA_COMPUTE_20
OR CUDA_COMPUTE_70
OR CUDA_COMPUTE_72
OR CUDA_COMPUTE_75
OR CUDA_COMPUTE_80
OR CUDA_COMPUTE_86
)
SET(FALLBACK OFF)
ELSE()
Expand All @@ -70,8 +72,8 @@ LIST(LENGTH COMPUTES_DETECTED_LIST COMPUTES_LEN)
IF(${COMPUTES_LEN} EQUAL 0 AND ${FALLBACK})
MESSAGE(STATUS "You can use -DCOMPUTES_DETECTED_LIST=\"AB;XY\" (semicolon separated list of CUDA Compute versions to enable the specified computes")
MESSAGE(STATUS "Individual compute versions flags are also available under CMake Advance options")
LIST(APPEND COMPUTES_DETECTED_LIST "30" "50" "60" "70")
MESSAGE(STATUS "No computes detected. Fall back to 30, 50, 60 70")
LIST(APPEND COMPUTES_DETECTED_LIST "30" "50" "60" "70" "80")
MESSAGE(STATUS "No computes detected. Fall back to 30, 50, 60, 70, 80")
ENDIF()

LIST(LENGTH COMPUTES_DETECTED_LIST COMPUTES_LEN)
Expand All @@ -90,7 +92,7 @@ MACRO(SET_COMPUTE VERSION)
ENDMACRO(SET_COMPUTE)

# Iterate over compute versions. Create variables and enable computes if needed
FOREACH(VER 20 30 32 35 37 50 52 53 60 61 62 70 72 75)
FOREACH(VER 20 30 32 35 37 50 52 53 60 61 62 70 72 75 80 86)
OPTION(CUDA_COMPUTE_${VER} "CUDA Compute Capability ${VER}" OFF)
MARK_AS_ADVANCED(CUDA_COMPUTE_${VER})
IF(${CUDA_COMPUTE_${VER}})
Expand Down
96 changes: 48 additions & 48 deletions cmake/FindGLFW.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -20,66 +20,66 @@
include(FindPackageHandleStandardArgs)

if (WIN32)
# Find include files
find_path(
GLFW_INCLUDE_DIR
NAMES GLFW/glfw3.h
PATHS
$ENV{PROGRAMFILES}/include
${GLFW_ROOT_DIR}/include
DOC "The directory where GLFW/glfw.h resides")
# Find include files
find_path(
GLFW_INCLUDE_DIR
NAMES GLFW/glfw3.h
PATHS
$ENV{PROGRAMFILES}/include
${GLFW_ROOT_DIR}/include
DOC "The directory where GLFW/glfw.h resides")

# Use glfw3.lib for static library
if (GLFW_USE_STATIC_LIBS)
set(GLFW_LIBRARY_NAME glfw3)
else()
set(GLFW_LIBRARY_NAME glfw3dll)
endif()
# Use glfw3.lib for static library
if (GLFW_USE_STATIC_LIBS)
set(GLFW_LIBRARY_NAME glfw3)
else()
set(GLFW_LIBRARY_NAME glfw3dll)
endif()

# Find library files
find_library(
GLFW_LIBRARY
NAMES ${GLFW_LIBRARY_NAME}
PATHS
$ENV{PROGRAMFILES}/lib
${GLFW_ROOT_DIR}/lib)
# Find library files
find_library(
GLFW_LIBRARY
NAMES ${GLFW_LIBRARY_NAME}
PATHS
$ENV{PROGRAMFILES}/lib
${GLFW_ROOT_DIR}/lib)

unset(GLFW_LIBRARY_NAME)
unset(GLFW_LIBRARY_NAME)
else()
# Find include files
find_path(
GLFW_INCLUDE_DIR
NAMES GLFW/glfw.h
PATHS
/usr/include
/usr/local/include
/sw/include
/opt/local/include
DOC "The directory where GL/glfw.h resides")
# Find include files
find_path(
GLFW_INCLUDE_DIR
NAMES GLFW/glfw.h
PATHS
/usr/include
/usr/local/include
/sw/include
/opt/local/include
DOC "The directory where GL/glfw.h resides")

# Find library files
# Try to use static libraries
find_library(
GLFW_LIBRARY
NAMES glfw3
PATHS
/usr/lib64
/usr/lib
/usr/local/lib64
/usr/local/lib
/sw/lib
/opt/local/lib
${GLFW_ROOT_DIR}/lib
DOC "The GLFW library")
# Find library files
# Try to use static libraries
find_library(
GLFW_LIBRARY
NAMES glfw3
PATHS
/usr/lib64
/usr/lib
/usr/local/lib64
/usr/local/lib
/sw/lib
/opt/local/lib
${GLFW_ROOT_DIR}/lib
DOC "The GLFW library")
endif()

# Handle REQUIRD argument, define *_FOUND variable
find_package_handle_standard_args(GLFW DEFAULT_MSG GLFW_INCLUDE_DIR GLFW_LIBRARY)

# Define GLFW_LIBRARIES and GLFW_INCLUDE_DIRS
if (GLFW_FOUND)
set(GLFW_LIBRARIES ${OPENGL_LIBRARIES} ${GLFW_LIBRARY})
set(GLFW_INCLUDE_DIRS ${GLFW_INCLUDE_DIR})
set(GLFW_LIBRARIES ${OPENGL_LIBRARIES} ${GLFW_LIBRARY})
set(GLFW_INCLUDE_DIRS ${GLFW_INCLUDE_DIR})
endif()

# Hide some variables
Expand Down
44 changes: 22 additions & 22 deletions cmake/FindGLM.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
# Find GLM
#
# Try to find GLM : OpenGL Mathematics.
# This module defines
# This module defines
# - GLM_INCLUDE_DIRS
# - GLM_FOUND
#
# The following variables can be set as arguments for the module.
# - GLM_ROOT_DIR : Root library directory of GLM
# - GLM_ROOT_DIR : Root library directory of GLM
#
# References:
# - https://github.com/Groovounet/glm/blob/master/util/FindGLM.cmake
Expand All @@ -18,34 +18,34 @@
include(FindPackageHandleStandardArgs)

if (WIN32)
# Find include files
find_path(
GLM_INCLUDE_DIR
NAMES glm/glm.hpp
PATHS
$ENV{PROGRAMFILES}/include
${GLM_ROOT_DIR}/include
DOC "The directory where glm/glm.hpp resides")
# Find include files
find_path(
GLM_INCLUDE_DIR
NAMES glm/glm.hpp
PATHS
$ENV{PROGRAMFILES}/include
${GLM_ROOT_DIR}/include
DOC "The directory where glm/glm.hpp resides")
else()
# Find include files
find_path(
GLM_INCLUDE_DIR
NAMES glm/glm.hpp
PATHS
/usr/include
/usr/local/include
/sw/include
/opt/local/include
${GLM_ROOT_DIR}/include
DOC "The directory where glm/glm.hpp resides")
# Find include files
find_path(
GLM_INCLUDE_DIR
NAMES glm/glm.hpp
PATHS
/usr/include
/usr/local/include
/sw/include
/opt/local/include
${GLM_ROOT_DIR}/include
DOC "The directory where glm/glm.hpp resides")
endif()

# Handle REQUIRD argument, define *_FOUND variable
find_package_handle_standard_args(GLM DEFAULT_MSG GLM_INCLUDE_DIR)

# Define GLM_INCLUDE_DIRS
if (GLM_FOUND)
set(GLM_INCLUDE_DIRS ${GLM_INCLUDE_DIR})
set(GLM_INCLUDE_DIRS ${GLM_INCLUDE_DIR})
endif()

# Hide some variables
Expand Down
27 changes: 0 additions & 27 deletions external/include/GL/Copying.txt

This file was deleted.

Loading