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
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
endif()

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

cuda_add_executable(${CMAKE_PROJECT_NAME}
Expand All @@ -78,7 +78,7 @@ cuda_add_executable(${CMAKE_PROJECT_NAME}

target_link_libraries(${CMAKE_PROJECT_NAME}
src
#stream_compaction # TODO: uncomment if using your stream compaction
stream_compaction # TODO: uncomment if using your stream compaction
${CORELIBS}
)

Expand Down
74 changes: 69 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,75 @@ 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)
* Nischal K N
* Tested on: Windows 7, i7-4790 @ 3.60GHz 16GB, Quadro K20 1GB (Moore 100B Lab)

### (TODO: Your README)
### SUMMARY
This project implements a path tracer using GPU. Following are the features implemented
* Shading kernel with BSDF evaluation
* Caching of first bounce intersection
* Sorting of intersections by material type
* Refraction using Schlick's approximation
* Stochastic Antialiasing
* Path termination by stream compaction using `thrust::partition` and `StreamCompaction::efficient`

*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.
An analysis of performance with different combinations of caching, sorting and stream compaction is documented. Also the performance improvement due to stream compaction is shown.

### OUTPUT
![](img/reflection.png)

### BUILD INSTRUCTIONS
* To setup cuda development environment use [this guide](https://github.com/nischalkn/Project0-CUDA-Getting-Started/blob/master/INSTRUCTION.md#part-1-setting-up-your-development-environment)
* Once the environment is set up, to Build and run the project follow [this](https://github.com/nischalkn/Project0-CUDA-Getting-Started/blob/master/INSTRUCTION.md#part-3-build--run)

### PARAMETERS
* `SORTING` - `1` or `0`, Enable\\Disable sorting intersections by material
* `CACHING` - `1` or `0`, Enable\\Disable caching of first intersection for same camera position
Note: Enabling this disables Antialiasing
* `EFFICIENT_COMPACTION` - `0`,`1` or `2`, Set the type of stream compaction for termination of rays.
* `0` - No termination, fixed depth
* `1` - efficient stream compaction using `StreamCompaction::efficient::compact`
* `2` - stream compaction using `thrust::partition`
* `PROFILE` - `1` or `0`, Print execution time for 2000 iterations

### ANALYSIS
Eight different experiments were conducted with different combinations of parameters. The time taken for executing 2000 iterations was recorded and the findings are shown in the table below

|Expt |`COMPACTION`|`SORTING`|`CACHING`|Total Time(s)|Average Time(ms)|
|:---:|:---:|:---:|:---:|:---:|:---:|
|1 | 0 | 0 | 0 |886.652 | 443.327|
|2 | 0 | 0 | 1 |825.312 |412.657 |
|3 | 0 | 1 | 0 |2849.136 |1424.569 |
|4 | 0 | 1 | 1 |2793.896 |1396.949 |
|5 | 1 | 0 | 0 |656.751 |328.375 |
|6 | 1 | 0 | 1 |591.242 |295.621 |
|7 | 1 | 1 | 0 |1660.564 |830.283 |
|8 | 1 | 1 | 1 |1594.92 |797.461 |

From the table it can be seen that the execution is the fastest when caching is enabled as expected. However enabling sorting should ideally speed up the execution but the findings were contradictory. This was because the overhead of sorting overshadows any advantage gained from sequential memory access. A graph representing this data is shown below. Also enabling stream compaction speeds up the computation as terminated rays are removed from the buffer. The effect of this is evaluated in more detail in the following section.

![](img/expt.png)

## Effect of Stream Compaction on execution times
An Analysis was conducted to understand the effect of early termination of rays using stream compaction. The time taken by the implementation to bounce and shade the rays over different depth levels were recorded. It was averaged over 500 iterations for 8 depth/bounces.

![](img/compaction.png)

From the graph it is seen that initially at depth 2 when there are not many rays that are terminated, using stream compaction is bad as the overhead of terminating the few rays is not advantageous. But as the number of bounces increase, the time taken to complete the iteration drastically improves.

## Refraction
Refraction was implemented using using Schlick's approximation. The following is the output

![](img/refraction.png)

## Antialiasing
Antialiasing was implemented by jittering the initial ray from the camera. Antialiasing is disabled when `CACHING` is enabled.

![](img/AA.png)

## Efficient Stream compaction
Rays are terminated and removed from the pool when the number of remaining bounces are zero. This is done using stream compaction. An efficient scan is used to compact the rays. The performance of this implementation vs `thrust::partition` is as follows

![](img/thrust.png)

The efficient method performs slower than the thrust implementation because of the time needed for memory allocation of intermediate binary and scan arrays.
Binary file added img/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 img/compaction.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/expt.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/reflection.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/reflectionWithoutAA.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/refraction.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/thrust.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 26 additions & 0 deletions src/interactions.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,30 @@ void scatterRay(
// TODO: implement this.
// A basic implementation of pure-diffuse shading will just call the
// calculateRandomDirectionInHemisphere defined above.
thrust::uniform_real_distribution<float> u01(0, 1);
glm::vec3 newDir;
if (u01(rng) < m.hasReflective) {
newDir = glm::reflect(pathSegment.ray.direction, normal);
pathSegment.color *= m.specular.color;
}
else if (u01(rng) < m.hasRefractive) {
float cosTheta = glm::dot(pathSegment.ray.direction, normal);
float R0 = powf(((1 - m.indexOfRefraction) / (1 + m.indexOfRefraction)), 2);
float R = R0 + (1 - R0)*powf((1 - glm::abs(cosTheta)), 5);


if (cosTheta < 0)
newDir = glm::refract(pathSegment.ray.direction, normal, 1.0f/m.indexOfRefraction);
else
newDir = glm::refract(pathSegment.ray.direction, normal, m.indexOfRefraction);
pathSegment.color *= m.specular.color;
}
else
{
newDir = calculateRandomDirectionInHemisphere(normal, rng);
}
pathSegment.color *= m.color;
pathSegment.remainingBounces--;
pathSegment.ray.direction = newDir;
pathSegment.ray.origin = intersect + normal * 0.001f;
}
Loading