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
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ set(headers
src/sceneStructs.h
src/preview.h
src/utilities.h
external/include/tiny_gltf.h
external/include/json.hpp
external/include/gltf-loader.h
external/include/mesh.h
external/include/material.h
)

set(sources
Expand Down
16 changes: 16 additions & 0 deletions CMakeSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
// See https://go.microsoft.com/fwlink/?linkid=834763 for more information about this file.
"configurations": [
{
"name": "x64-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"inheritEnvironments": [ "msvc_x64_x64" ],
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": ""
}
]
}
68 changes: 62 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,69 @@
CUDA Path Tracer
================

**University of Pennsylvania, CIS 565: GPU Programming and Architecture, Project 3**
* Haorong Yang
* [LinkedIn](https://www.linkedin.com/in/haorong-henry-yang/)
* Tested on: Windows 10 Home, i7-10750H @ 2.60GHz 16GB, GTX 2070 Super Max-Q (Personal)

<img src="img/rongbig1959.png" width="650">

3D Model Credit: [Rồng by @Husky on Sketchfab](https://sketchfab.com/3d-models/rong-b61cffbfbe66495b97a9a101b1859bbc?cursor=bz0xJnA9MjQ5)



## Features:
### Graphics
* Bidirectional Scattering Distribution Functions (BSDF): Ideal Diffuse, Specular Reflection, Refraction
* Physically-based depth-of-field (by jittering rays within an aperture)
* Stochastic Sampled Antialiasing
* Arbitrary Mesh loading

### Optimization
* Path termination using stream compaction
* Sorting pathSegments by material type
* Acceleration by caching first bounce

### Bidirectional Scattering Distribution Functions
Ideal Diffuse | Specular Reflection | Transmissive (Refraction)
:-------------------------:|:-------------------------:|:-----------------------
<img src="img/diffusive.png" width="330">| <img src="img/reflective.png" width="330">| <img src="img/transmissive.png" width="330">


### Physically-Based Depth of Field
No Depth of Field | With Depth of Field
:-------------------------:|:-------------------------:
<img src="img/nodepth.png" width="500">| <img src="img/cornell5000samp.png" width="500"> |


### Stochastic Sampled Antialiasing
No Anti Aliasing | With Anti Aliasing
:-------------------------:|:-------------------------:
<img src="img/no_anti_alias.PNG" width="500">| <img src="img/antialias.PNG" width="500"> |

### Arbitrary Mesh Loading
Avocado | Duck | Rồng
:-------------------------:|:-------------------------:|:-----------------------
<img src="img/avocado2396.png" width="330">| <img src="img/duck315.png" width="330">| <img src="img/rong.png" width="330">


3D Model Credit: [Khronos Group GLTF Sample Models](https://github.com/KhronosGroup/glTF-Sample-Models), [Rồng by @Husky on Sketchfab](https://sketchfab.com/3d-models/rong-b61cffbfbe66495b97a9a101b1859bbc?cursor=bz0xJnA9MjQ5)



### Optimization
Below is a chart that compares the runtime of 5 iterations when toggling one or both of "sorting by material" and "chaching first bounce" off for rendering scene at the top of this readme.

<img src="img/chart.PNG" width="500">

* (TODO) YOUR NAME HERE
* Tested on: (TODO) Windows 22, i7-2222 @ 2.22GHz 22GB, GTX 222 222MB (Moore 2222 Lab)
Sorting the ray/path segments by material type will increase performance by making memory access contiguous hence more efficient; when there are a lot of materials, but not so much when there are limited materials, for example, in the conrell box test scene.

### (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.
### Bloopers
<img src="img/blooper1.png" width="270"> <img src="img/blooper2.png" width="270"> <img src="img/blooper4.png" width="270">

### References
* [PBRT] Physically Based Rendering, Second Edition: From Theory To Implementation. Pharr, Matt and Humphreys, Greg. 2010.
* CIS565 Slides
* https://learnopengl.com/PBR/Theory
* https://raytracing.github.io/books/RayTracingInOneWeekend.html#dielectrics/refraction
* http://wwwx.cs.unc.edu/~rademach/xroads-RT/RTarticle.html#:~:text=Its%20color%20is%20given%20by,way%20out%20into%20the%20scene.
166 changes: 166 additions & 0 deletions external/include/gltf-loader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
#ifndef EXAMPLE_GLTF_LOADER_H_
#define EXAMPLE_GLTF_LOADER_H_

#include <stdexcept>
#include <string>
#include <vector>

#include "material.h"
#include "mesh.h"

namespace example {

/// Adapts an array of bytes to an array of T. Will advace of byte_stride each
/// elements.
template <typename T>
struct arrayAdapter {
/// Pointer to the bytes
const unsigned char *dataPtr;
/// Number of elements in the array
const size_t elemCount;
/// Stride in bytes between two elements
const size_t stride;

/// Construct an array adapter.
/// \param ptr Pointer to the start of the data, with offset applied
/// \param count Number of elements in the array
/// \param byte_stride Stride betweens elements in the array
arrayAdapter(const unsigned char *ptr, size_t count, size_t byte_stride)
: dataPtr(ptr), elemCount(count), stride(byte_stride) {}

/// Returns a *copy* of a single element. Can't be used to modify it.
T operator[](size_t pos) const {
if (pos >= elemCount)
throw std::out_of_range(
"Tried to access beyond the last element of an array adapter with "
"count " +
std::to_string(elemCount) + " while getting elemnet number " +
std::to_string(pos));
return *(reinterpret_cast<const T *>(dataPtr + pos * stride));
}
};

/// Interface of any adapted array that returns ingeger data
struct intArrayBase {
virtual ~intArrayBase() = default;
virtual unsigned int operator[](size_t) const = 0;
virtual size_t size() const = 0;
};

/// Interface of any adapted array that returns float data
struct floatArrayBase {
virtual ~floatArrayBase() = default;
virtual float operator[](size_t) const = 0;
virtual size_t size() const = 0;
};

/// An array that loads interger types, returns them as int
template <class T>
struct intArray : public intArrayBase {
arrayAdapter<T> adapter;

intArray(const arrayAdapter<T> &a) : adapter(a) {}
unsigned int operator[](size_t position) const override {
return static_cast<unsigned int>(adapter[position]);
}

size_t size() const override { return adapter.elemCount; }
};

template <class T>
struct floatArray : public floatArrayBase {
arrayAdapter<T> adapter;

floatArray(const arrayAdapter<T> &a) : adapter(a) {}
float operator[](size_t position) const override {
return static_cast<float>(adapter[position]);
}

size_t size() const override { return adapter.elemCount; }
};

#pragma pack(push, 1)

template <typename T>
struct v2 {
T x, y;
};
/// 3D vector of floats without padding
template <typename T>
struct v3 {
T x, y, z;
};

/// 4D vector of floats without padding
template <typename T>
struct v4 {
T x, y, z, w;
};

#pragma pack(pop)

using v2f = v2<float>;
using v3f = v3<float>;
using v4f = v4<float>;
using v2d = v2<double>;
using v3d = v3<double>;
using v4d = v4<double>;

struct v2fArray {
arrayAdapter<v2f> adapter;
v2fArray(const arrayAdapter<v2f> &a) : adapter(a) {}

v2f operator[](size_t position) const { return adapter[position]; }
size_t size() const { return adapter.elemCount; }
};

struct v3fArray {
arrayAdapter<v3f> adapter;
v3fArray(const arrayAdapter<v3f> &a) : adapter(a) {}

v3f operator[](size_t position) const { return adapter[position]; }
size_t size() const { return adapter.elemCount; }
};

struct v4fArray {
arrayAdapter<v4f> adapter;
v4fArray(const arrayAdapter<v4f> &a) : adapter(a) {}

v4f operator[](size_t position) const { return adapter[position]; }
size_t size() const { return adapter.elemCount; }
};

struct v2dArray {
arrayAdapter<v2d> adapter;
v2dArray(const arrayAdapter<v2d> &a) : adapter(a) {}

v2d operator[](size_t position) const { return adapter[position]; }
size_t size() const { return adapter.elemCount; }
};

struct v3dArray {
arrayAdapter<v3d> adapter;
v3dArray(const arrayAdapter<v3d> &a) : adapter(a) {}

v3d operator[](size_t position) const { return adapter[position]; }
size_t size() const { return adapter.elemCount; }
};

struct v4dArray {
arrayAdapter<v4d> adapter;
v4dArray(const arrayAdapter<v4d> &a) : adapter(a) {}

v4d operator[](size_t position) const { return adapter[position]; }
size_t size() const { return adapter.elemCount; }
};

///
/// Loads glTF 2.0 mesh
///
bool LoadGLTF(const std::string &filename, float scale,
std::vector<gltfMesh<float> > *meshes,
std::vector<Material> *materials, std::vector<gltfTexture> *textures);

} // namespace example

#endif // EXAMPLE_GLTF_LOADER_H_
Loading