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
14 changes: 7 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ target_link_libraries(${CMAKE_PROJECT_NAME}
${CORELIBS}
)

add_custom_command(
TARGET ${CMAKE_PROJECT_NAME}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_SOURCE_DIR}/shaders
${CMAKE_BINARY_DIR}/shaders
)
#add_custom_command(
#TARGET ${CMAKE_PROJECT_NAME}
#POST_BUILD
#COMMAND ${CMAKE_COMMAND} -E copy_directory
# ${CMAKE_SOURCE_DIR}/shaders
# ${CMAKE_BINARY_DIR}/shaders
#)
169 changes: 164 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,170 @@ 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)
* Henry Zhu
* [Github](https://github.com/Maknee), [LinkedIn](https://www.linkedin.com/in/henry-zhu-347233121/), [personal website](https://maknee.github.io/), [twitter](https://twitter.com/maknees1), etc.
* Tested on: Windows 10 Home, Intel i7-4710HQ @ 2.50GHz 22GB, GTX 870M (Own computer)

## Nice Kuda pics

![](main.png)

- * Knight in the scene is from a game called [Runescape](https://oldschool.runescape.com/)

## What is a path tracer?

A pathtracer is a method of rendering realistic images that I would say is better than the images produced by ray tracing.

Essentially, a pathtracer shoots a ray into the image from each pixel (screen space) into the scene and the collects all the colors from the material it hits until it reaches a light source. If the light source is not reached in x bounces, the ray does not contribute to the color. The ray is produced for each iteration in order to average out the inconsistenties and to average out the color for the pixel that is drawn.

## Building / Usage

### Building
- Build using cmake or cmake-gui
- Open sln project in visual studio

### Running
- ./cis565_path_tracer.exe ..\scenes\main.txt

## What features of my path tracer implement?

- The path tracer works
- Refraction with fresnel effects
- Reflection
- Anti-aliasing
- Motion-blur
- Model loading (using [tinyObj](https://github.com/syoyo/tinyobjloader)) with toggleable bounding volume intersection culling

## Reflection/Refraction

### Refraction

![](refraction.png)

### Refraction with fresnel (half refraction, half reflection)

![](refraction_reflection.png)

### Reflection

![](reflection.png)

### Refraction/Reflection evaluation

This feature consists of creating reflection and refraction on objects, so they are realistic like real world reflection/refraction occurances.

Refraction occurs when light that passes through an object blends as shown by light bending when entering water.

Reflection occurs on objects like a mirror.

One can can combine reflection/refraction using fresnel values.

#### Performance

The performance was not that much worse than computing just with diffuse. The only real way that performance could be impacted is the amount of calculation that has to be done in the glm::reflect/glm::refract computations.

#### GPU/CPU implementation (hypothetical)

The GPU version should be no different from the CPU version other than having each ray's reflection/refraction computation become parallized (the only benefit I see from the GPU, which is still huge because instead of doing 800 x 600 rays in serial, the GPU handles them in parallel.

#### Future optimizations

As of right now, I'm using a fresnel calculation that could be replaced with a more optimized technique.

For a combination of refraction/reflection, I use a branch and compute a refraction or reflection ray based on the percentage of the refraction/reflection. Branches are bad especially in this case since the branch is computed randomly. There is defnitely a way to do this in a predictable way.

## Anti-aliasing

![](anti-aliasing.png)

### Anti-aliasing evaluation

Anti-aliasing is used when pixels become too distinctive and one "averages" out the pixels color over its neighbors. This is done easily in the path tracer as one just needs to move the ray slightly towards a direction randomly.

#### Performance

The performance is definitely being hit here in the sense that one need to compute more iterations in order to get a better image. This is because since the rays are not always hitting the same point and more randomly in the points around the point one used to hit, it takes longer to average out the colors in order to get a crisp image.

#### GPU/CPU implementation (hypothetical)

The GPU version would be much different than the CPU version. In the GPU version, one needs to just shift the ray slightly to add anti-aliasing. In the CPU version, one needs to keep track of the pixels and sample it with the pixels around it (way more code and a lot more iterations as well)

#### Future optimizations

Optimizations could defnitely be added. Instead of having a ray shift right and left every time, one could do it x times over an iterval or average the pixels out at the end when the image wants to be saved. This would create a not-as-strong anti-aliasing effect, but would improve performance.

There are possibly other anti-aliasing methods for the path tracer, but I have not dug into this as of yet.

## Object loading

![](rune-boi.png)

### Object loading evaluation

Object loading is awesome! When I ran it the first time, I was shocked at how slow the render was. This is due to the check against every single triangle to see if the ray intersects the object. So, the more triangle the model has, the more slow the path tracer becomes. The volume bound testing definitely helps by checking if the ray even hits in the vinicity of the object's triangles by basically doing a AABB testing.

#### Performance

Performance is definitely a big problem here. Testing against every triangle in the mesh (which could be thousands if not millions) is intense, even for the GPU. On my current computer setup, each iteration takes approximately one second for a mesh with a couple thousand triangles.

#### GPU/CPU implementation (hypothetical)

One can sort of compare the GPU with the CPU in this scenario. The GPU implementation (if done with optimizations and with a powerful GPU), can check the intersections for all triangles in parallel (unlike mine, which checks triangles with one thread). Currently, however, if I were to port my implementation to the CPU, it would run the same except, it's not in parallel for computing all the rays.

#### Future optimizations

There are optimizations that could make model loading/intersection a world's ton faster.

KD-trees are the first to come to mind. KD-trees are essentially boxes for each set of triangles in a model to test for instead of testing for all the triangles for the model.

The triangle intersection itself can be done in parallel (with a strong enough GPU) instead of checking all the triangles for each ray.

Models could use less triangles for speed up.

## Motion blur

![](blur.png)

### Motion blur evaluation

Motion blur creates a "blur" effect where an object image was taken as if it was in motion.

#### Performance

Motion blur did not impact performance. This is due to only moving the object slightly to offset it a bit to create the motion blur effect.

#### GPU/CPU implementation (hypothetical)

I can see the CPU implementation being very similar to the GPU implementation. The object would move in a particular direction before being drawn (and this repeats multiple times in the CPU implementation, unlike GPU, which happens by default since the path tracer goes in iterations).

#### Future optimizations

Optimizations could be drawing an object x number of times spaced out instead of looping and drawing the object each iteration.

Also, for some objects such as sphere, one could "scretch" it out to cover more area for the motion blur to work on.

### Stream compaction

![](stream_compact.png)

The above image shows the effects of stream compaction. Stream compaction helps with filtering out rays that have been terminated by hitting the light or going out of bounds.

### Stream compaction on scenes open / closed

![](stream_compact_open_closed.png)

When a scene is closed vs when it is open, how does stream compaction get affected? What one could expect is for stream compaction to be less effective in a closed scene. The only way for a ray to terminate early is to hit a light source in a closed scene. In an open scene, a ray terminates by hitting a light source or going out of bounds (ie, outside the scene)

## Third party usage

### Code
- [TinyObj](https://github.com/syoyo/tinyobjloader)

### Book
- [PBRT](https://www.pbrt.org/)




### (TODO: Your README)

*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.

Binary file added anti-aliasing.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 blur.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 main.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 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 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 refraction_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 rune-boi.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions scenes/knight2.mtl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Blender MTL File: 'untitled.blend'
# Material Count: 1

newmtl Material.013
Ns 96.078431
Ka 1.000000 1.000000 1.000000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
192 changes: 192 additions & 0 deletions scenes/main.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
// 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 0
REFR 1
REFRIOR 1.5
EMITTANCE 0

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

// Specular white
MATERIAL 6
RGB 0 .4 .7
SPECEX 0
SPECRGB .98 .98 .98
REFL .3
REFR 0
REFRIOR 1.5
EMITTANCE 0

// Specular white
MATERIAL 7
RGB .8 .3 0
SPECEX 0
SPECRGB .98 .98 .98
REFL 0
REFR 0
REFRIOR 1.5
EMITTANCE 0

// Specular white
MATERIAL 8
RGB 0 .4 .7
SPECEX 0
SPECRGB .98 .98 .98
REFL 0
REFR 0
REFRIOR 1.5
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 -2.5 2 -1
ROTAT 0 0 0
SCALE 3 3 3

// Mesh
OBJECT 7
mesh
knight2.obj
material 6
TRANS 0 0 -3
ROTAT 0 0 0
SCALE 1 1 1

// Sphere
OBJECT 8
sphere
material 5
TRANS 2.5 2 -1
ROTAT 0 0 0
SCALE 3 3 3

// Sphere
OBJECT 9
mesh
sword2.obj
material 7
TRANS 2.5 4 -2
ROTAT 0 0 0
SCALE 1 1 1

// Sphere
OBJECT 10
mesh
sword2.obj
material 8
TRANS -2.5 4 -2
ROTAT 0 0 0
SCALE 1 1 1
Loading