Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
cc94327
Diffuse + stream compaction base working
Sep 29, 2021
d034576
Finish core features
Sep 29, 2021
8ec0fde
Initial refraction working
Oct 1, 2021
31a8b04
Attempted to fix refraction (probably correct now), DOF without focal…
Oct 2, 2021
a63a85b
Fix refraction, add depth of field
Oct 3, 2021
aaf2526
Initial bounding box calculations
Oct 3, 2021
0d47a10
Triangle intersections draft for mesh loading, thoughts on path guiding
Oct 4, 2021
3364ef9
Refraction working
Oct 5, 2021
ddb94ff
Buggy mesh loader code
Oct 5, 2021
a5d5e69
Get ray/triangle intersection working on manual triangle
Oct 5, 2021
a4dc8fd
Initial mesh loading done
Oct 6, 2021
7f9c2ba
Finish mesh loading, bounding box
Oct 6, 2021
3fa25a4
Fix mesh loading bug
Oct 7, 2021
788d508
Initial anti-aliasing, some renders
Oct 7, 2021
e7b2791
Fix anti aliasing, more renders
Oct 7, 2021
be906db
Fix first bounce cache, add renders
Oct 7, 2021
1019d7c
Update README.md
asalexan Oct 8, 2021
dc5dc35
Add files via upload
asalexan Oct 8, 2021
6b763f4
Add files via upload
asalexan Oct 8, 2021
16cbaec
Update README.md
asalexan Oct 8, 2021
49f29d3
Add files via upload
asalexan Oct 9, 2021
0b89f2d
Update README.md
asalexan Oct 9, 2021
3ed2269
Add files via upload
asalexan Oct 9, 2021
85efe15
Update README.md
asalexan Oct 9, 2021
75dbcdf
Update README.md
asalexan Oct 9, 2021
d0650a5
Update README.md
asalexan Oct 9, 2021
c9d1f0a
Add final renders
Oct 9, 2021
ca193ad
One last render to add
Oct 9, 2021
dc7e599
Merge branch 'main' of https://github.com/asalexan/Project3-CUDA-Path…
Oct 9, 2021
0e5f1ec
Add cropped image
asalexan Oct 9, 2021
1f3611e
Update README.md
asalexan Oct 9, 2021
153aa41
Add files via upload
asalexan Oct 10, 2021
03a1852
Add files via upload
asalexan Oct 10, 2021
52ad45f
Update README.md
asalexan Oct 10, 2021
b33e8e2
Add anti-alias markup
asalexan Oct 10, 2021
3fa3f21
Add files via upload
asalexan Oct 10, 2021
b57dea0
Add marked up mirror scene
asalexan Oct 10, 2021
f162c7e
Update README.md
asalexan Oct 10, 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
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ set(headers
src/sceneStructs.h
src/preview.h
src/utilities.h
src/tiny_obj_loader.h
)

set(sources
Expand Down
163 changes: 158 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,164 @@ 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)
* Ashley Alexander-Lee
* [LinkedIn](linkedin.com/in/asalexanderlee), [Personal Website](https://asalexanderlee.myportfolio.com/)
* Tested on: Windows 10, i7-6700 @ 3.40GHz 16GB, Quadro P1000 (Moore 100A Lab)

### (TODO: Your README)
![Mirror Scene](img/final_renders/mirror_scene.png)
*Mirrored hall effect, iterations: 5,000, depth: 8, resolution: 1200x1200*

![Mirror Scene Markup](img/final_renders/mirror_scene2.png)

Usage
=====

#### Installation
1. Use a Cuda-enabled Windows machine
2. Clone this repository
3. `mkdir build` in the folder
4. Run CMake, and select "Visual Studio 2019" and "x64"
5. Configure and generate binaries
6. Open the .sln file in VS2019
7. In "Properties" -> "Debugging" -> "Command Arguments", type `../scenes/name_of_scene.txt`
8. Be sure to run in Release Mode

#### In-Code Toggles
There are a few macros I defined to turn certain features on or off. Most are located in pathtrace.cu:
- `SORT_MATERIALS` (bool) - sort rays by material after each bounce
- `CACHE_FIRST_BOUNCE` (bool) - cache the shaded rays after the first bounce on the first iteration so that the remaining iterations don't have to recompute the first bounce -- as long as it's deterministic (i.e. DOF and anti-aliasing aren't enabled)
- `DOF` (bool) - apply depth of field
- `FOCAL_LEN` (float) - focal length for DOF
- `ANTIALIASING` (bool) - apply anti-aliasing

In scene.cpp and intersections.h, we have:
- `USE_BB` (bool) - use bounding box


Description
=============
In this project, I implemented a pathtracer on the GPU by evaluating "batches" of rays during each iteration. At each iteration, I performed the following steps:

**1. Generate camera rays**
- Save these `PathSegment`s to an array on the GPU
- If `ANTI_ALIASING` is enabled, the reference point is jittered
- If `DOF` is enabled, a point is sampled from a disk to represent the camera position, and a focal length determines the slice of the viewing frustuum we're casting to

**2. Compute intersections with scene**
- Save these `ShadeableIntersection`s to an array on the GPU

**3. Shade each ray according to the material**
- Multiply the `PathSegment` color by the color of the intersection
- If `SORT_BY_MATERIAL` is enabled, rays are sorted based on material after this step

**4. Generate new ray directions based on the material**
- There are three materials supported: 1) Diffuse, 2) Specular, and 3) Dialectric
- Diffuse rays are scattered based on semi-random sampling of a hemisphere
- Specular rays are scattered in exactly one direction (reflected across the normal)
- Dialectric rays are either reflected or refracted based on a Fresnel coefficient
- Alter the origin and direction of the `Ray` in each `PathSegment`

**5. Cull rays if 1) they hit nothing, or 2) they hit the light**
- Rays are flagged to terminate if they match the termination conditions listed
- I maintain a list of pointers to active rays, and use stream compaction to remove all pointers to rays that are terminated.

**6. Perform steps 2 - 5 until we've reached max depth or all rays are culled**

**7. Add the resulting colors to the pixels**

Features
========
### Dielectrics
I added support for transmissive materials, where the reflective and refractive components are based on a fresnel coefficient. The coefficient determines the likelihood of scattering a reflective or a refractive ray.

| | |
|-|-|
|![Refraction 1](img/final_renders/refraction1.png) | ![Refraction 2](img/final_renders/refraction2.png)|

### Depth of Field

| Focal Length: 10 | Focal Length: 15 |
| ---------------- | ---------------- |
| ![DOF2](img/final_renders/cornell.2021-10-07_19-19-01z.10000samp.png) |![DOF1](img/final_renders/cornell.2021-10-07_19-03-36z.10000samp.png)|

The camera origin is jittered by sampling from a disk, and the focal length determines the slice of the view frustuum we're casting a ray to.

### Mesh Loading
I added support for obj loading and mesh display. I used [tinyobjloader](https://github.com/tinyobjloader/tinyobjloader) to read an obj path and triangulate the mesh. I then created a Triangle struct and a vector containing vectors of triangles that is owned by the scene. I populated each triangle and pushed it to the vector, then got the pointer to said vector and saved it to the geometry. Finally, I copied the triangle data over to the GPU before running the integrator.

I also added a computeIntersection function for the mesh, which iterates through all of the mesh's triangles, and computes the intersection of the given ray with each triangle, finding the minimum distance along the ray to the nearest triangle.

![Mesh Example](img/final_renders/cornell.2021-10-09_20-37-05z.2503samp.png)

I provide an option `USE_BB`, which will create a bounding box for the mesh. The savings for this depends on how much of the space the mesh takes up -- if the mesh encompasses most of the viewing space, the bounding box offers little help efficiency-wise. However, if it takes up a fraction of the viewing space, you are saving a large amount of time that would be spent iterating over and testing for intersection with triangles. I performed a test to demonstrate this, where I timed the rendering of the same mesh at two different scales, which you can see below.

| Lamp: Scale 0.5 | Lamp: Scale 4 |
| --------------- | ------------- |
| ![Lamp Scale 0.5](img/performance_renders/scaleHalfBB.png) | ![Lamp Scale 4](img/performance_renders/scale4BB.png) |

You can see that the bounding box saves much more time for the half-sized lamp than for the scale 4 lamp.

![How Bounding Boxes Improve Mesh Render Time](img/performance_renders/HowBoundingBoxesImproveMeshRenderingTime2.png)

### Anti-Aliasing
I jittered the pixel point by some fractional value to achieve anti-aliasing, as seen below. I rendered this scene at a low resolution (200x200) so that the improvements are obvious.

![Anti-Alias Comparison](img/final_renders/anti-alias_comparison2.png)

As you can see below, enabling anti-aliasing doesn't seem to have a major effect on runtime. There is an additional cost associated with jittering the rays, but this is minimal.

![Performance Impact Anti-Aliasing](img/performance_renders/PerformanceImpactofAnti-Aliasing.png)

*Run on Cornell Box, iterations: 5000, depth: 8, 800x800*

Optimizations
============

### Stream Compaction

I created an array of pointers on the GPU, all pointing to existing rays. I used Thrust's `partition` function to sort all of the "truthy", i.e. non-terminatable, rays to the front of the array, and maintained a pointer to the back of the "truthy" values. This array of pointers to rays is used for future intersection and shading calculations, as it represents the collection of rays that are active. You can see below the number of rays that are culled at every depth.

I ran the following on a simple cornell box with a diffuse sphere in the middle, and removed the side and back walls for the "Open" configuration. I only ran 1 iteration, with max depth 100 and resolution 800x800 (this is why you will notice the number of rays start at 640,000). I only show up to depth 50, since the flatline trend continues on to 100.

![Reduction in Rays Due to Stream Compaction Chart](img/ReductioninRaysDueToStreamCompaction.png)

You can see almost a logarithmic decrease in the rays for the open cornell box configuration, and a more gradual decrease for the closed cornell box. This makes sense, since the termination conditions are: 1) if the ray hits nothing, and 2) if the ray hits a light. The likelihood of hitting nothing is very high in the open cornell box, since about a third of the screen is empty space, whereas it is very low for the closed cornell box. This results in a high number of rays being terminated each depth for the open cornell box, leading the iteration to finish early at depth 20, instead of 100.

### Sorting by Material

I have a toggleable option `SORT_BY_MATERIAL` that will sort the rays by material after each depth. This means that rays with similar bounce futures will be grouped together, increasing the likelihood that warps will finish together, and fewer rays will be left idle.

As it stands, sorting by material seems to have a negative impact on runtime performance. I rendered the following scene that contains 6 spheres with interleaved materials with and without sorting by material. I imagine that there are so few materials in the scene that the cost of sorting at each depth is not offset by the savings gained by grouping rays with similar materials together. If you were to drastically increase the number of materials and objects in the scene, I would guess you would see more of an improvement.

![Sorting By Materials Render](img/performance_renders/sortMats5000it8depth.png)

*800x800, iterations: 5000, depth: 8*

![Performance Impactof Sorting Materials](img/performance_renders/PerformanceImpactofSortingRaysByMaterial.png)

### Caching the First Bounce

I also have a toggleable option `CACHE_FIRST_BOUNCE` which, if enabled, saves the first bounce data in a GPU array. Future iterations can then skip a depth, harvesting the first bounce data from the appropriate GPU array. This shaves off about `1 / depth` amount of pathtrace computation. Note that this option cannot be enabled if `DOF` or `ANTIALIASING` are enabled, since the first bounce will be non-deterministic.

You can see significant time savings as the resolution is increased, as you save on that much more computation.

![Performance Impact of Caching First Bounce](img/performance_renders/HowCachingFirstBounceImprovesPerformance.png)

Bloopers
=======

#### Skeleton Lamp

![Skeleton Lamp Blooper](img/skeletonLamp5000samples.png)

![Skeleton Lamp GIF](img/meshNormalTest.gif)

#### Let the Rain Come Down

![Sample Blooper](img/cornell.2021-10-02_20-42-09z.125samp.png)

#### My Refractive Rays Got Lost

![Refraction Blooper](img/cornell.2021-10-02_17-43-48z.213samp.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.

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/ReductioninRaysDueToStreamCompaction.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/bbTestScale2.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/bbTestScaleHalf.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/cornell.2021-09-29_18-04-26z.5000samp.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/cornell.2021-10-01_18-51-47z.2459samp.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/cornell.2021-10-01_18-54-37z.5000samp.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/cornell.2021-10-02_16-49-57z.169samp.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/cornell.2021-10-02_17-43-48z.213samp.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/cornell.2021-10-02_18-03-36z.5000samp.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/cornell.2021-10-02_18-42-26z.2649samp.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/cornell.2021-10-02_19-15-19z.5000samp.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/cornell.2021-10-02_19-19-55z.5000samp.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/cornell.2021-10-02_19-38-48z.429samp.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/cornell.2021-10-02_19-45-33z.168samp.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/cornell.2021-10-02_20-30-26z.154samp.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/cornell.2021-10-02_20-30-50z.60samp.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/cornell.2021-10-02_20-31-01z.240samp.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/cornell.2021-10-02_20-31-24z.215samp.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/cornell.2021-10-02_20-42-09z.125samp.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/cornell.2021-10-03_17-25-19z.5000samp.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/cornell.2021-10-06_17-53-00z.1055samp.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/cornell.2021-10-06_17-53-00z.179samp.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/cornell.2021-10-06_17-53-00z.2026samp.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/cornell.2021-10-06_17-53-00z.648samp.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/cornell.2021-10-06_20-00-07z.5000samp.png
Binary file added img/cornell.2021-10-06_20-18-36z.693samp.png
Binary file added img/cornell.2021-10-06_20-56-12z.5000samp.png
Binary file added img/cornell.2021-10-06_21-51-49z.147samp.png
Binary file added img/cornell.2021-10-06_22-20-24z.5000samp.png
Binary file added img/cornell.2021-10-07_17-19-38z.5000samp.png
Binary file added img/cornell.2021-10-07_17-21-32z.5000samp.png
Binary file added img/cornell.2021-10-07_17-44-57z.5000samp.png
Binary file added img/cornell.2021-10-07_17-47-55z.5000samp.png
Binary file added img/cornell.2021-10-07_17-50-46z.5000samp.png
Binary file added img/cornell.2021-10-07_19-56-52z.5000samp.png
Binary file added img/cornell.2021-10-07_20-01-42z.5000samp.png
Binary file added img/cornell.2021-10-07_20-07-44z.5000samp.png
Binary file added img/cornell.2021-10-07_20-19-45z.1samp.png
Binary file added img/cornell.2021-10-07_20-37-36z.5000samp.png
Binary file added img/cornell.2021-10-07_22-27-01z.1samp.png
Binary file added img/cornell.2021-10-07_22-28-01z.1samp.png
Binary file added img/cornell.2021-10-07_22-31-44z.1samp.png
Binary file added img/final_renders/anti-alias-comparison.png
Binary file added img/final_renders/anti-alias_comparison2.png
Binary file added img/final_renders/mirror_scene.png
Binary file added img/final_renders/mirror_scene2.png
Binary file added img/final_renders/refraction1.png
Binary file added img/final_renders/refraction2.png
Binary file added img/meshNormalTest.gif
Binary file added img/performance_renders/aax2.png
Binary file added img/performance_renders/no_aa.png
Binary file added img/performance_renders/scale4BB.png
Binary file added img/performance_renders/scaleHalfBB.png
Binary file added img/performance_renders/sortMats5000it8depth.png
Binary file added img/skeletonLamp5000samples.png
51 changes: 44 additions & 7 deletions scenes/cornell.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,26 @@ REFR 0
REFRIOR 0
EMITTANCE 0

// Transmissive white
MATERIAL 5
RGB .98 .98 .98
SPECEX 0
SPECRGB 0 0 0
REFL 0
REFR 1
REFRIOR 1.5
EMITTANCE 0

// Diffuse blue
MATERIAL 6
RGB .5 .5 .98
SPECEX 0
SPECRGB 0 0 0
REFL 0
REFR 0
REFRIOR 0
EMITTANCE 0

// Camera
CAMERA
RES 800 800
Expand All @@ -66,7 +86,7 @@ cube
material 0
TRANS 0 10 0
ROTAT 0 0 0
SCALE 3 .3 3
SCALE 4 .3 4

// Floor
OBJECT 1
Expand All @@ -87,7 +107,7 @@ SCALE .01 10 10
// Back wall
OBJECT 3
cube
material 1
material 6
TRANS 0 5 -5
ROTAT 0 90 0
SCALE .01 10 10
Expand All @@ -109,9 +129,26 @@ ROTAT 0 0 0
SCALE .01 10 10

// Sphere
//OBJECT 6
//sphere
//material 1
//TRANS 0 4 -1
//ROTAT 0 0 0
//SCALE 6 6 6

// cube
//OBJECT 6
//cube
//material 1
//TRANS -0.0 4 1
//ROTAT 0 0 45
//SCALE 3 3 3

// mesh
OBJECT 6
sphere
material 4
TRANS -1 4 -1
ROTAT 0 0 0
SCALE 3 3 3
mesh
material 1
FILENAME ../objs/lamp.obj
TRANS 0 2 -5
ROTAT 0 90 0
SCALE 0.5 0.5 0.5
Loading