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
47 changes: 42 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,48 @@ 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)
* Zhiyu Lei
* [LinkedIn](https://www.linkedin.com/in/zhiyu-lei/), [Github](https://github.com/Zhiyu-Lei)
* Tested on: Windows 22, i7-2222 @ 2.22GHz 22GB, GTX 222 222MB (CETS Virtual Lab)

### (TODO: Your README)
![](img/README/output.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 output is generated from the scene in [scenes/customize.txt](scenes/customize.txt))

### Project Features
#### A shading kernel with BSDF evaluation for diffuse and specular-reflective surfaces
For a non-reflective (i.e. diffuse) surface like the side wall in the output image, a ray intersected with the surface changes its direction to a cosine-weighted random direction in a hemisphere around the surface normal.

For a specular-reflective surface like the metal ball in the output image, a ray intersected with the surface has a 50% probability to change its direction according to the specular reflection law, while another 50% probability to change its direction as diffuse reflection.

#### Path continuation/termination using Stream Compaction
A path terminates when the corresponding ray intersects with a light source or no longer intersects with any objects. Those terminated paths no longer need to be traced any more and can already have their pixels colored. In this case, Stream Compaction can be applied to filter and continue with only unterminated paths for the next bounces.

The plot below shows how many unterminated paths remain after each bounce within one iteration in the reference scene:
![](img/README/rays-bounce.png)

Also, for a closed scene where no light can escape, Stream Compaction can still improve efficiency. This is because though every ray must intersect with some objects, there can be some rays terminating by intersecting with light sources.

#### Sorting intersections and pathSegments by material types
In each bounce after the intersections are computed, the intersections and the corresponding pathSegments are reordered so that the same materials are contiguous in memory before shading. However, I did not experience much performance improvement, and the process of sorting by material types could be even more costly than randomly accessing in memory.

#### Refraction with Frensel effects using Snell's law
For a refractive material like the glass ball or the purple crystal cube in the output image, a ray intersected with the material has a 99% probability to pass through the material following Snell's law, while another 1% probability to change its direction as diffuse or specular reflection on the surface.

#### Stochastic Sampled Antialiasing
The following two images show a comparison of outputs after 50 iterations between with and without antialiasing where the rays are somewhat jittered through the pixels. The output without antialiasing is quite noisier than the one with, particularly on the glass ball.
|With antialiasing|Without antialiasing|
|:---:|:---:|
|![](img/README/ref.50samp.png)|![](img/README/no-antialiasing.50samp.png)|

#### Direct lighting by taking a final ray directly to a random point on an emissive object acting as a light source
The following two images show a comparison of outputs after 50 iterations between with and without direct lighting where the final rays intersect with objects acting as light sources. The output without direct lighting is darker than the one with, and even comtains some incorrect black pixels.
|With direct lighting|Without direct lighting|
|:---:|:---:|
|![](img/README/ref.50samp.png)|![](img/README/no-direct-lighting.50samp.png)|

#### Jittered sampling for Monte Carlo ray tracing
The following two images show a comparison of outputs after 50 iterations between jittered sampling (on a grid with the same resolution as the output) and normal random sampling. The output with normal random sampling is a little bit noisier than the one with jittered sampling.
|Jittered sampling|Random sampling|
|:---:|:---:|
|![](img/README/ref.50samp.png)|![](img/README/random-sampling.50samp.png)|
Binary file added img/README/no-antialiasing.50samp.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/README/no-direct-lighting.50samp.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/README/output.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/README/random-sampling.50samp.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/README/rays-bounce.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/README/ref.50samp.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion scenes/cornell.txt
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,4 @@ sphere
material 4
TRANS -1 4 -1
ROTAT 0 0 0
SCALE 3 3 3
SCALE 3 3 3
149 changes: 149 additions & 0 deletions scenes/customize.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// 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

MATERIAL 5
RGB .98 .98 .98
SPECEX 0
SPECRGB .98 .98 .98
REFL 0
REFR 1
REFRIOR 0.9
EMITTANCE 0

MATERIAL 6
RGB .85 .35 .85
SPECEX 0
SPECRGB .85 .35 .85
REFL 1
REFR 1
REFRIOR 0.9
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

OBJECT 7
sphere
material 5
TRANS 2.5 3 1
ROTAT 0 0 0
SCALE 3 3 3

OBJECT 8
cube
material 6
TRANS 3 6 0
ROTAT 45 45 45
SCALE 2 2 2
28 changes: 27 additions & 1 deletion src/interactions.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,37 @@ glm::vec3 calculateRandomDirectionInHemisphere(
__host__ __device__
void scatterRay(
PathSegment & pathSegment,
glm::vec3 intersect,
glm::vec3 intersectOut, glm::vec3 intersectIn,
glm::vec3 normal,
const Material &m,
thrust::default_random_engine &rng) {
// TODO: implement this.
// A basic implementation of pure-diffuse shading will just call the
// calculateRandomDirectionInHemisphere defined above.
float counteract = 1.f;
if (m.hasRefractive) {
thrust::uniform_real_distribution<float> u01(0, 1);
float prob = u01(rng);
if (prob < 0.99f) {
pathSegment.ray.origin = intersectIn;
pathSegment.ray.direction = glm::refract(pathSegment.ray.direction, normal, m.indexOfRefraction);
pathSegment.color *= m.color;
return;
}
}
pathSegment.ray.origin = intersectOut;
if (m.hasReflective) {
thrust::uniform_real_distribution<float> u01(0, 1);
float prob = u01(rng);
if (prob < 0.5f) {
pathSegment.ray.direction = glm::reflect(pathSegment.ray.direction, normal);
pathSegment.color *= m.specular.color * counteract * 2.f;
pathSegment.remainingBounces--;
return;
}
counteract *= 2.f;
}
pathSegment.ray.direction = calculateRandomDirectionInHemisphere(normal, rng);
pathSegment.color *= m.color * counteract;
pathSegment.remainingBounces--;
}
Loading