Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
e5a180f
* implemented path tracing w/ relfection & diffuse & stream compaction
ziedbha Sep 29, 2018
2c3f61a
+ new scenes and bloopers
ziedbha Sep 29, 2018
8f50737
* fixed refraction
ziedbha Sep 29, 2018
b64bd97
* fixed bug due to stream compaction
ziedbha Sep 30, 2018
4efc955
+ added bloopers/results
ziedbha Sep 30, 2018
40bf5e3
* cached first bounce
ziedbha Sep 30, 2018
8c28105
* sorted by material id for better performance
ziedbha Sep 30, 2018
44e6ffd
* implemented anti-aliasing & schlick refraction
ziedbha Sep 30, 2018
de0a460
* implemented depth of field
ziedbha Sep 30, 2018
163cd44
* fixed refraction for the 100th time
ziedbha Sep 30, 2018
a7c1c71
+ added tinyobjloader dependencies
ziedbha Sep 30, 2018
a14440e
+ added obj loading with box volume culling
ziedbha Oct 1, 2018
ab2c0ad
* short comments on bounding box intersection testing
ziedbha Oct 1, 2018
0aa36f4
+ images
ziedbha Oct 1, 2018
53d0c89
+ imgs
ziedbha Oct 1, 2018
6e34ac4
* first readme update
ziedbha Oct 1, 2018
35b7efb
+ intro image
ziedbha Oct 1, 2018
ef0a7c9
* updated readme
ziedbha Oct 1, 2018
9193191
+ images, * computing geometrical normals
ziedbha Oct 1, 2018
4733f8c
Merge branch 'master' of https://github.com/ziedbha/Project3-CUDA-Pat…
ziedbha Oct 1, 2018
ba442f7
* updated aa & dof readme
ziedbha Oct 1, 2018
966a8ee
* updated aa explanation
ziedbha Oct 1, 2018
6033423
+ added obj loading images
ziedbha Oct 1, 2018
5b51d3f
Merge branch 'master' of https://github.com/ziedbha/Project3-CUDA-Pat…
ziedbha Oct 1, 2018
9102da9
Update README.md
ziedbha Oct 1, 2018
f4e4332
Update README.md
ziedbha Oct 1, 2018
09f3bdc
Update README.md
ziedbha Oct 1, 2018
19fd3a2
+ materials images
ziedbha Oct 1, 2018
4aaddef
Merge branch 'master' of https://github.com/ziedbha/Project3-CUDA-Pat…
ziedbha Oct 1, 2018
0969968
Update README.md
ziedbha Oct 1, 2018
708e856
* images + scenes
ziedbha Oct 1, 2018
d9b8729
Merge branch 'master' of https://github.com/ziedbha/Project3-CUDA-Pat…
ziedbha Oct 1, 2018
eafac86
Update README.md
ziedbha Oct 1, 2018
ba2e91d
+ more images & scenes
ziedbha Oct 1, 2018
a8a863a
Update README.md
ziedbha Oct 2, 2018
075ab53
Update README.md
ziedbha Oct 2, 2018
788bb0a
+ graphs * final edit on pathtrace.cu
ziedbha Oct 2, 2018
173d1f8
* changed warning message in loadGeom
ziedbha Oct 2, 2018
a70c418
Merge branch 'master' of https://github.com/ziedbha/Project3-CUDA-Pat…
ziedbha Oct 2, 2018
8c021cd
Update README.md
ziedbha Oct 2, 2018
c12f926
* img
ziedbha Oct 2, 2018
596e9bb
Merge branch 'master' of https://github.com/ziedbha/Project3-CUDA-Pat…
ziedbha Oct 2, 2018
01a34e8
Update README.md
ziedbha Oct 2, 2018
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
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ endif()
include_directories(.)
#add_subdirectory(stream_compaction) # TODO: uncomment if using your stream compaction
add_subdirectory(src)
add_subdirectory(tinyobjloader)

cuda_add_executable(${CMAKE_PROJECT_NAME}
"src/main.h"
Expand All @@ -83,6 +84,7 @@ cuda_add_executable(${CMAKE_PROJECT_NAME}
target_link_libraries(${CMAKE_PROJECT_NAME}
src
#stream_compaction # TODO: uncomment if using your stream compaction
tinyobj
${CORELIBS}
)

Expand Down
137 changes: 132 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,138 @@ CUDA Path Tracer

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

* (TODO) YOUR NAME HERE
* Tested on: (TODO) Windows 22, i7-2222 @ 2.22GHz 22GB, GTX 222 222MB (Moore 2222 Lab)
* Ziad Ben Hadj-Alouane
* [LinkedIn](https://www.linkedin.com/in/ziadbha/), [personal website](https://www.seas.upenn.edu/~ziadb/)
* Tested on: Windows 10, i7-8750H @ 2.20GHz, 16GB, GTX 1060

### (TODO: Your README)
# Project Goal
<p align="center">
<img src="https://github.com/ziedbha/Project3-CUDA-Path-Tracer/blob/master/images/top.png"/>
</p>

*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.
In this project, I implemented a Path Tracer using the CUDA parallel computing platform. Path Tracing is a computer graphics Monte Carlo method of rendering images of three-dimensional scenes such that the global illumination is faithful to reality.

# Path Tracing Intro
<p align="center">
<img width="300" height="400" src="https://github.com/ziedbha/Project3-CUDA-Path-Tracer/blob/master/images/explanation.png"/>
</p>
In simple terms, a path tracer fires rays from each pixel, which would bounce off in many directions depending on the objects in the scene. If the ray is fortunate enough, it would hit an illuminating surface (lightbulb, sun, etc...), and would cause the first object it hit to be illuminated, much like how light travels towards our eyes.

## Issues
Path tracing is computationally expensive since for each pixel, our rays might hit numerous geometries along the way. Checking intersections with each geometry is expensive, which is why we employ optimization techniques (culling, caching, stream compaction, material sorting) as well as use a parallel computing platform (CUDA) to take advantage of the GPUs cores.

## Stream Compaction, Caching, & Sorting Optimizations
### Stream Compaction
[Stream Compaction](https://github.com/ziedbha/Project2-Stream-Compaction) helps by ommitting rays that aren't used in an iteration anymore. This happens when a ray hits nothing, or runs out of bounces (e.g hits a light source). This allows for a fewer blocks to launch, and less divergence in threads. The effects are great in different types of open scenes (tall, numerous materials, high-poly count) as shown below:
![](images/stream_compaction_scenes.png)

However, the effects are less impressive when it comes to closed scenes, since stream compaction only comes in when rays hit a light source or natrually run out of permitted bounces. Overall, performance improves a lot with stream compaction.
![](images/open_vs_closed_compact.png)

### Caching
Since in the beginning of every iteration we fire the exact same ray from the exact same pixel, then we cache the intersection results so that we do not repeat them in subsequent iterations. Note that this feature does not work when anti-aliasing is enabled since anti-aliasing adds noise to the first rays, making them probabilistically unequal in subsequent iterations.

### Material Sorting

| Without Sorting | With Sorting |
| ------------- | ----------- |
| <p align="center"><img width="300" height="350" src="https://github.com/ziedbha/Project3-CUDA-Path-Tracer/blob/master/images/no_sort.png"/></p>| <p align="center"><img width="300" height="350" src="https://github.com/ziedbha/Project3-CUDA-Path-Tracer/blob/master/images/with_sort.png"/></p> |

Before shading a ray, I performed an optimization that consisted in sorting the rays by the material type they hit. This allowed the CUDA warps (sets of threads) to diverge less in execution, saving more time. As the graphs above show, there are more branches in the unsorted case, and even more divergence as captured by the CUDA profiler.

## 3D Model Importing (.obj)
| Dedocahedron | Sword |
| ------------- | ----------- |
| ![](images/deca.png) | ![](images/sword.png) |

To import 3D .obj files, I used TinyObjLoader which is a good parser for this specific file format. .obj files contain vertex information (positions, normals, texture coordinates) as well as triangulation information. Implementing this feature meant that I needed to store separate triangles for one mesh, with each triangle containing the correct vertex data.

As expected, high poly-count meshes take longer to render (see below)

| Wahoo | [Spider](https://poly.google.com/view/cbFePDoI8yi) |
| ------------- | ----------- |
| ![](images/wahoo.png) | ![](images/spider.png) |

### Performance & Optimization
Since GPUs aren't able to use resizable arrays, I couldn't store vectors of triangles for each mesh. Instead, I loaded my meshes this way:

| Mesh 1 | Triangle 1-1 | Triangle 1-... | Triangle 1-n | ... | Mesh 2 | Triangle 2-1 | Triangle 2- ...| Triangle 2-m |
| ------------- | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- |
| End Index of Triangle data | Vertex data | Vertex data | Vertex data | ... | End Index of Triangle data | Vertex data | Vertex data | Vertex data |

So that when I tested intersections against a mesh, I would access the next index to find the first triangle, and I would access the end index to find the last triangle of the mesh.

To test intersections against the mesh, I did two optimizations:
1. *Bounding-Volume Culling*: I compute the bounds of the mesh and surround it by a bounding box. Using this bounding box, I can check if a ray can potentially hit the mesh. If it can't, then no intersection is possible, so we skip it. Else, we test intersections against all triangles.
2. *Deferred Intersection Calculations*: I calculate intersections against triangles in a mesh in one giant batch. In other words, I only keep the closest triangle I intersected for a ray, and THEN perform all needed calculations. This significantly improves the performance of mesh intersection since for high poly-count meshes, simple calculations such as point retrieval become expensive.

## Anti-Aliasing
| Without Anti-Aliasing | With Anti-Aliasing |
| ------------- | ----------- |
| ![](images/aa_none.png) | ![](images/aa.png) |

In computer graphics, anti-aliasing is a software technique used to diminish stair-step like lines that should be smooth instead. This usually occurs when the resolution isn't high enough. In path tracing, we apply anti-aliasing by firing the ray with additional noise. If the ray is supposed to color pixel (x,y), we sample more colors around that pixel, and average them out to color pixel (x,y).

The picture below explains the approach. My implementation is represented by the image on the right. A dot is a sample (ray), a square is a pixel.

<p align="center">
<img width="300" height="100" src="https://github.com/ziedbha/Project3-CUDA-Path-Tracer/blob/master/images/aa_exp.png"/>
</p>

### Performance & Optimization
Anti-Aliasing has no impact on performance since it is essentially 2 more lines of code per ray. All rays do the same anti-aliasing computation, which means that no warps diverge. No further optimization needed.

## Depth of Field

| Without Depth of Field | With Depth of Field |
| ------------- | ----------- |
| ![](images/dof_none.png) | ![](images/dof.png) |

In optics, depth of field is the distance about the plane of focus where objects appear acceptably sharp in an image. In path tracing, this is achieved by adding noise to the ray direction about the focal point, as explained in this [article](https://medium.com/@elope139/depth-of-field-in-path-tracing-e61180417027).

### Performance & Optimization
Depth of Field is just a few extra vector computations per ray, and much like anti-aliasing, it has no impact on performance. All rays do the same computation, which means that no warps diverge. No further optimization needed.


## Materials Support
<p align="center">
<img src="https://github.com/ziedbha/Project3-CUDA-Path-Tracer/blob/master/images/mix.png"/>
</p>
My implementation supports diffuse and specular materials. For specular materials, I support pure refractive, reflective, and transmissive materials.

### Diffuse
<p align="center">
<img src="https://github.com/ziedbha/Project3-CUDA-Path-Tracer/blob/master/images/diffuse.png"/>
</p>

### Specular Reflective
<p align="center">
<img src="https://github.com/ziedbha/Project3-CUDA-Path-Tracer/blob/master/images/reflect.png"/>
</p>

### Specular Refractive
<p align="center">
<img src="https://github.com/ziedbha/Project3-CUDA-Path-Tracer/blob/master/images/refract.png"/>
</p>

### Transmissive using Schlick's Approximation
<p align="center">
<img src="https://github.com/ziedbha/Project3-CUDA-Path-Tracer/blob/master/images/transmit.png"/>
</p>

# Bloopers & Bugs
| Weak Seed for Randomly Generated Numbers | Incorrect Access of Path Index in a Thread | Missing Internal Total Reflection & Wrong Normals |
| ------------- | ----------- | ------------- |
| <p align="center"><img width="200" height="200" src="https://github.com/ziedbha/Project3-CUDA-Path-Tracer/blob/master/images/seed_bug.png"/></p> | <p align="center"><img width="200" height="200" src="https://github.com/ziedbha/Project3-CUDA-Path-Tracer/blob/master/images/stream_compaction_bug.png"/></p> | <p align="center"><img width="200" height="200" src="https://github.com/ziedbha/Project3-CUDA-Path-Tracer/blob/master/images/refraction_bug.png"/></p> |

# Build Instructions
1. Install [CMake](https://cmake.org/install/)
2. Install [Visual Studio 2015](https://docs.microsoft.com/en-us/visualstudio/welcome-to-visual-studio-2015?view=vs-2015) with C++ compativility
3. Install [CUDA 8](https://developer.nvidia.com/cuda-80-ga2-download-archive) (make sure your GPU supports this)
4. Clone this Repo
5. Create a folder named "build" in the root of the local repo
6. Navigate to the build folder and run "cmake-gui .." in a CLI
7. Configure the build with Visual Studio 14 2015 Win64, then generate the solution
8. Run the solution using Visual Studio 2015
10. Build cis_565_path_tracer and set it as Startup Project
9. Run cis_565_path_tracer with command line arguments: ../scenes/name_of_scene.txt
Binary file added images/aa.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 images/aa_exp.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 images/aa_none.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 images/deca.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 images/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 images/dof.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 images/dof_none.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 images/explanation.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 images/mix.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 images/no_sort.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 images/open_vs_closed_compact.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 images/reflect.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 images/refract.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 images/refraction_bug.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 images/seed_bug.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 images/spider.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 images/stream_compaction_bug.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 images/stream_compaction_scenes.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 images/sword.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 images/top.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 images/transmit.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 images/wahoo.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 images/with_sort.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 34 additions & 2 deletions scenes/cornell.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,33 @@ REFR 0
REFRIOR 0
EMITTANCE 0

// Specular white
// Specular blue (refr + ref)
MATERIAL 4
RGB .8 .98 .98
SPECEX 0
SPECRGB .8 .98 .98
REFL 0.5
REFR 0.3
REFRIOR 1.4
EMITTANCE 0

// Specular blue (ref only)
MATERIAL 5
RGB .8 .98 .98
SPECEX 0
SPECRGB .8 .98 .98
REFL 1
REFR 0
REFRIOR 0
EMITTANCE 0


// Diffuse White
MATERIAL 5
RGB .98 .98 .98
SPECEX 0
SPECRGB .98 .98 .98
REFL 1
REFL 0
REFR 0
REFRIOR 0
EMITTANCE 0
Expand All @@ -58,6 +79,8 @@ FILE cornell
EYE 0.0 5 10.5
LOOKAT 0 5 0
UP 0 1 0
FOCAL 10
LENSR 0.5


// Ceiling light
Expand Down Expand Up @@ -115,3 +138,12 @@ material 4
TRANS -1 4 -1
ROTAT 0 0 0
SCALE 3 3 3

// Sphere
OBJECT 7
sphere
material 5
TRANS 4 4 -1
ROTAT 0 0 0
SCALE 3 3 3

176 changes: 176 additions & 0 deletions scenes/cube.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
// Emissive material (light)
MATERIAL 0
RGB 1 1 1
SPECEX 0
SPECRGB 0 0 0
REFL 0
REFR 0
REFRIOR 0
EMITTANCE 4

// Diffuse white
MATERIAL 1
RGB .98 .98 .98
SPECEX 0
SPECRGB 0 0 0
REFL 0
REFR 0
REFRIOR 0
EMITTANCE 0

// Diffuse red
MATERIAL 2
RGB .85 .35 .35
SPECEX 0
SPECRGB 0 0 0
REFL 0
REFR 0
REFRIOR 0
EMITTANCE 0

// Diffuse blue
MATERIAL 3
RGB .35 .35 .85
SPECEX 0
SPECRGB 0 0 0
REFL 0
REFR 0
REFRIOR 0
EMITTANCE 0

// neutral
MATERIAL 4
RGB 1 1 1
SPECEX 0
SPECRGB 1 1 1
REFL 0
REFR 0
REFRIOR 0
EMITTANCE 0

// Diffuse 1
MATERIAL 5
RGB .50 .98 .5
SPECEX 0
SPECRGB .50 .98 .5
REFL 0
REFR 0
REFRIOR 0
EMITTANCE 0

// Diffuse 1
MATERIAL 6
RGB .2 .2 .98
SPECEX 0
SPECRGB .2 .2 .98
REFL 0.5
REFR 0.6
REFRIOR 1.3
EMITTANCE 0

// Diffuse red
MATERIAL 7
RGB .8 .0 .0
SPECEX 0
SPECRGB .98 .7 .8
REFL 0
REFR 0
REFRIOR 0
EMITTANCE 0

// Diffuse yellow
MATERIAL 8
RGB .8 .8 .3
SPECEX 0
SPECRGB .98 .98 .0
REFL 0
REFR 0
REFRIOR 0
EMITTANCE 0

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


// Ceiling light
OBJECT 0
cube
material 0
TRANS 0 10 0
ROTAT 0 0 0
SCALE 6 .3 6

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

// Ceiling
OBJECT 2
cube
material 1
TRANS 0 10 0
ROTAT 0 0 90
SCALE .01 10 10

// Back wall
OBJECT 3
cube
material 1
TRANS 0 5 -5
ROTAT 0 90 0
SCALE .01 10 10

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

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

// Mesh
OBJECT 6
mesh ../models/cube.obj
material 6
TRANS -4 6 -2
ROTAT 0 45 45
SCALE 1 1 1


// Mesh
OBJECT 7
mesh ../models/cube.obj
material 7
TRANS 0 4 -2
ROTAT 0 50 0
SCALE 1 2 1

// Mesh
OBJECT 8
mesh ../models/cube.obj
material 8
TRANS -2 2 0
ROTAT 0 30 0
SCALE 1 1 2
Loading