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 3: Bowen Bao #15

Open
wants to merge 8 commits into
base: master
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
53 changes: 48 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,54 @@ 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)
* Bowen Bao
* Tested on: Windows 10, i7-6700K @ 4.00GHz 32GB, GTX 1080 8192MB (Personal Computer)

### (TODO: Your README)
## Overview

*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.
Here's the list of features of this project:

1. Core Features:
* Shading kernel with BSDF evaluation.
* Path continuation/termination using Stream Compaction.
* First bounce intersection cache.
2. Extra Features:
* Refraction with Frensel effects using Schlick's approximation.
* Stochastic Sampled Antialiasing.
* Direct lighting.

![](/img/cornell_final.png)

## Instruction to Run

You can change the setup of the program in file utilities.h, where First bounce caching, antialiasing and direct lighting are all togglable(note that since first bounce caching and antialiasing are conflicting features, only antialiasing is active if both are set to be true).

## Performance Analysis
### Performance of different implementation

![](/img/process_time.png)

Here's the test result for each of the methods. The tests are run with the block size of 128. The average process time of each iteration is shown in the graph. We could observe that the total number of iterations doesn't affect the average performance very much. We could also observe that by using stream compaction, the average process time actually increases.

![](/img/overhead.png)

This might due to that in this scenario, the overhead in our case here is mostly on cpu instead of gpu. Adding stream compaction is putting more pressure on the cpu side, since it has to copy the data from device to host and start the stream compaction procedure. Adding stream compaction may be more useful for higher resolution rendering, where the computation on the gpu side becomes the bottleneck.

## Extra Credits
### Refraction with Frensel effects using Schlick's approximation.
In this part I extended the shader to deal with refraction rays. The final effect can be viewed in the following graph. I followed the algorithm of http://www.scratchapixel.com/lessons/3d-basic-rendering/introduction-to-shading/reflection-refraction-fresnel in my implementation. As we could observe in the graph, we have both reflection and refraction for the glass material.

![](/img/cornell_glass.png)

### Stochastic Sampled Antialiasing.
I followed the algorithms in http://paulbourke.net/miscellaneous/aliasing/ when implementing the antialiasing feature. Observe in the following graph that we achieved much better effects with same performance.

![](/img/antialiasing.png)

### Direct lighting.
Most of the rays are wasted in our previous implementation, as they didn't contribute any color information because they hadn't hit the light source in their "last" bounce. With direct lighting however, we tried to make use of that information by adding an additional bounce at the end to reach the light source and record the color. Following are the comparison of rendering with and without direct lighting. At the same time, we are also comparing how the number of iterations affect the final result.

![](/img/cornell_dl_5000_1000.png)
![](/img/cornell_5000_1000.png)

As we could see in the graph, rendering with direct lighting achieves a brighter image under the same iteration. It also achieves a cleaner image much faster than rendering without direct lighting.
Binary file added img/antialiasing.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_5000_1000.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_dl_5000_1000.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_final.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_glass.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/overhead.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/process_time.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 12 additions & 2 deletions scenes/cornell.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ REFR 0
REFRIOR 0
EMITTANCE 0

// Glass
MATERIAL 5
RGB .85 .85 .85
SPECEX 1
SPECRGB 1 1 1
REFL 0
REFR 1
REFRIOR 2.2
EMITTANCE 0

// Camera
CAMERA
RES 800 800
Expand Down Expand Up @@ -111,7 +121,7 @@ SCALE .01 10 10
// Sphere
OBJECT 6
sphere
material 4
material 1
TRANS -1 4 -1
ROTAT 0 0 0
SCALE 3 3 3
SCALE 3 3 3
180 changes: 180 additions & 0 deletions scenes/cornell_custom.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
// Emissive material (light)
MATERIAL 0
RGB 1 1 1
SPECEX 0
SPECRGB 0 0 0
REFL 0
REFR 0
REFRIOR 0
EMITTANCE 5

// 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 green
MATERIAL 3
RGB .35 .85 .35
SPECEX 0
SPECRGB 0 0 0
REFL 0
REFR 0
REFRIOR 0
EMITTANCE 0

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

// Glass
MATERIAL 5
RGB .85 .85 .85
SPECEX 1
SPECRGB 1 1 1
REFL 0
REFR 1
REFRIOR 2.2
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


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

// 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

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

// Sphere 2
OBJECT 7
sphere
material 1
TRANS 1 6 -1.5
ROTAT 0 0 0
SCALE 3 3 3


// Left wall light
OBJECT 8
cube
material 0
TRANS -5 5 0
SCALE .3 3 3

// Right wall light
OBJECT 9
cube
material 0
TRANS 5 5 0
SCALE .3 3 3

// glass cube
OBJECT 10
cube
material 5
TRANS 3 3 4
ROTAT 2 10 7
SCALE 1 1 1

// glass cube 2
OBJECT 11
cube
material 5
TRANS 1.2 5.5 3
SCALE 1.5 1 1

// glass cube 3
OBJECT 12
cube
material 5
TRANS -3.49 .01 -3.49
SCALE 3 3 3

// Sphere 3
//OBJECT 13
//sphere
//material 5
//TRANS -4.249 9.249 -4.249
//ROTAT 0 0 0
//SCALE 1.5 1.5 1.5
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ set(SOURCE_FILES
"scene.cpp"
"scene.h"
"sceneStructs.h"
"stream.cu"
"preview.h"
"preview.cpp"
"utilities.cpp"
Expand Down
86 changes: 44 additions & 42 deletions src/intersections.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ __host__ __device__ float boxIntersectionTest(Geom box, Ray r,
glm::vec3 tmax_n;
for (int xyz = 0; xyz < 3; ++xyz) {
float qdxyz = q.direction[xyz];
/*if (glm::abs(qdxyz) > 0.00001f)*/ {
/* if (glm::abs(qdxyz) > 0.00001f) */{
float t1 = (-0.5f - q.origin[xyz]) / qdxyz;
float t2 = (+0.5f - q.origin[xyz]) / qdxyz;
float ta = glm::min(t1, t2);
Expand Down Expand Up @@ -100,45 +100,47 @@ __host__ __device__ float boxIntersectionTest(Geom box, Ray r,
* @return Ray parameter `t` value. -1 if no intersection.
*/
__host__ __device__ float sphereIntersectionTest(Geom sphere, Ray r,
glm::vec3 &intersectionPoint, glm::vec3 &normal, bool &outside) {
float radius = .5;

glm::vec3 ro = multiplyMV(sphere.inverseTransform, glm::vec4(r.origin, 1.0f));
glm::vec3 rd = glm::normalize(multiplyMV(sphere.inverseTransform, glm::vec4(r.direction, 0.0f)));

Ray rt;
rt.origin = ro;
rt.direction = rd;

float vDotDirection = glm::dot(rt.origin, rt.direction);
float radicand = vDotDirection * vDotDirection - (glm::dot(rt.origin, rt.origin) - powf(radius, 2));
if (radicand < 0) {
return -1;
}

float squareRoot = sqrt(radicand);
float firstTerm = -vDotDirection;
float t1 = firstTerm + squareRoot;
float t2 = firstTerm - squareRoot;

float t = 0;
if (t1 < 0 && t2 < 0) {
return -1;
} else if (t1 > 0 && t2 > 0) {
t = min(t1, t2);
outside = true;
} else {
t = max(t1, t2);
outside = false;
}

glm::vec3 objspaceIntersection = getPointOnRay(rt, t);

intersectionPoint = multiplyMV(sphere.transform, glm::vec4(objspaceIntersection, 1.f));
normal = glm::normalize(multiplyMV(sphere.invTranspose, glm::vec4(objspaceIntersection, 0.f)));
if (!outside) {
normal = -normal;
}

return glm::length(r.origin - intersectionPoint);
glm::vec3 &intersectionPoint, glm::vec3 &normal, bool &outside) {
float radius = .5;

glm::vec3 ro = multiplyMV(sphere.inverseTransform, glm::vec4(r.origin, 1.0f));
glm::vec3 rd = glm::normalize(multiplyMV(sphere.inverseTransform, glm::vec4(r.direction, 0.0f)));

Ray rt;
rt.origin = ro;
rt.direction = rd;

float vDotDirection = glm::dot(rt.origin, rt.direction);
float radicand = vDotDirection * vDotDirection - (glm::dot(rt.origin, rt.origin) - powf(radius, 2));
if (radicand < 0) {
return -1;
}

float squareRoot = sqrt(radicand);
float firstTerm = -vDotDirection;
float t1 = firstTerm + squareRoot;
float t2 = firstTerm - squareRoot;

float t = 0;
if (t1 < 0 && t2 < 0) {
return -1;
}
else if (t1 > 0 && t2 > 0) {
t = min(t1, t2);
outside = true;
}
else {
t = max(t1, t2);
outside = false;
}

glm::vec3 objspaceIntersection = getPointOnRay(rt, t);

intersectionPoint = multiplyMV(sphere.transform, glm::vec4(objspaceIntersection, 1.f));
normal = glm::normalize(multiplyMV(sphere.invTranspose, glm::vec4(objspaceIntersection, 0.f)));
if (!outside) {
normal = -normal;
}

return glm::length(r.origin - intersectionPoint);
}
Loading