diff --git a/README.md b/README.md
index 110697ce..c90660a2 100644
--- a/README.md
+++ b/README.md
@@ -3,11 +3,55 @@ 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)
+* Zirui Zang
+ * [LinkedIn](https://www.linkedin.com/in/zirui-zang/)
+* Tested on: Windows 10, AMD Ryzen 7 3700X @ 3.60GHz 32GB, RTX2070 SUPER 8GB (Personal)
-### (TODO: Your README)
+## Photorealistic Rendering by Tracing Rays
-*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.
+In real life, rays come from light source, bounce between object surfaces before entering our eyes. Each bounce off an object surface carries information of that surface. In ray-tracing rendering, we can start from the eye (image plane), trace backwards through each pixel to the world and eventually to the light source. Such ray-tracing is repeated thousands of times and color information is averaged to give photorealistic effects.
+
+
+
+
+
+
+
+
+
+
+### Surface Scattering
+
+Below list the 3 separate scattering surfaces implemented in this renderer. To make refracgive surface seen more realistic, schlicks approximation is used to make the surface the effect of Frenel reflections. Objects in the seen can use a combination of these 3 properties based on the bidirectional scattering distribution function (BSDF) of the surface.
+
+| Lambertian | Reflective | Refractive | with Color |
+| ------------ | ----------- | ----------- | ----------- |
+| ![](scenes/cornell.2021-10-03_23-27-37z.3488samp.png) | ![](scenes/cornell.2021-10-03_23-34-37z.4309samp.png) | ![](scenes/cornell.2021-10-03_23-43-33z.1964samp.png) | ![](scenes/cornell.2021-10-04_00-14-05z.1925samp.png) |
+
+## Features
+
+### Depth of Field
+Depth of Field is created by sampling with a non-zero aperture size.
+
+| Close Focus | Far Focus |
+| ------------- | ----------- |
+| ![](img/cornell.2021-10-05_19-34-14z.1858samp.png) | ![](img/cornell.2021-10-05_21-11-55z.5000samp.png) |
+
+
+### Anti-Aliasing
+Anti-Aliasing is implemented by sub-pixel sampling.
+
+| with Anti-Aliasing | without Anti-Aliasing |
+| ------------- | ----------- |
+| ![](img/aa1.png) | ![](img/aa0.png) |
+
+### Other Features
+1. .obj Mesh Import
+2. Toggleable option to cache the first bounce intersections for re-use across all subsequent iterations, when not using anti-aliasing. Is is not used because AA is a must.
+3. Elimiating terminated rays with Stream Compaction. This method definitely reduces empty thread launches and improves performance.
+4. Efficient attempt to sort the ray by the material type before shading. No efficient improvement is seen with this method.
diff --git a/img/aa0.png b/img/aa0.png
new file mode 100644
index 00000000..d1fa54d6
Binary files /dev/null and b/img/aa0.png differ
diff --git a/img/aa1.png b/img/aa1.png
new file mode 100644
index 00000000..04ca62b2
Binary files /dev/null and b/img/aa1.png differ
diff --git a/img/cornell.2021-10-05_17-10-50z.5000samp.png b/img/cornell.2021-10-05_17-10-50z.5000samp.png
new file mode 100644
index 00000000..bc89e089
Binary files /dev/null and b/img/cornell.2021-10-05_17-10-50z.5000samp.png differ
diff --git a/img/cornell.2021-10-05_19-34-14z.1858samp.png b/img/cornell.2021-10-05_19-34-14z.1858samp.png
new file mode 100644
index 00000000..c821e726
Binary files /dev/null and b/img/cornell.2021-10-05_19-34-14z.1858samp.png differ
diff --git a/img/cornell.2021-10-05_21-11-55z.5000samp.png b/img/cornell.2021-10-05_21-11-55z.5000samp.png
new file mode 100644
index 00000000..2f5985dc
Binary files /dev/null and b/img/cornell.2021-10-05_21-11-55z.5000samp.png differ
diff --git a/img/cornell.2021-10-05_21-17-44z.5000samp.png b/img/cornell.2021-10-05_21-17-44z.5000samp.png
new file mode 100644
index 00000000..07915c5c
Binary files /dev/null and b/img/cornell.2021-10-05_21-17-44z.5000samp.png differ
diff --git a/scenes/cornell.2021-10-03_23-27-37z.3488samp.png b/scenes/cornell.2021-10-03_23-27-37z.3488samp.png
new file mode 100644
index 00000000..d9102a57
Binary files /dev/null and b/scenes/cornell.2021-10-03_23-27-37z.3488samp.png differ
diff --git a/scenes/cornell.2021-10-03_23-34-37z.4309samp.png b/scenes/cornell.2021-10-03_23-34-37z.4309samp.png
new file mode 100644
index 00000000..4f0272f3
Binary files /dev/null and b/scenes/cornell.2021-10-03_23-34-37z.4309samp.png differ
diff --git a/scenes/cornell.2021-10-03_23-43-33z.1964samp.png b/scenes/cornell.2021-10-03_23-43-33z.1964samp.png
new file mode 100644
index 00000000..87ed08f8
Binary files /dev/null and b/scenes/cornell.2021-10-03_23-43-33z.1964samp.png differ
diff --git a/scenes/cornell.2021-10-04_00-14-05z.1925samp.png b/scenes/cornell.2021-10-04_00-14-05z.1925samp.png
new file mode 100644
index 00000000..6687c68e
Binary files /dev/null and b/scenes/cornell.2021-10-04_00-14-05z.1925samp.png differ
diff --git a/scenes/cornell.2021-10-04_19-03-52z.2097samp.png b/scenes/cornell.2021-10-04_19-03-52z.2097samp.png
new file mode 100644
index 00000000..4abd6a66
Binary files /dev/null and b/scenes/cornell.2021-10-04_19-03-52z.2097samp.png differ
diff --git a/scenes/cornell.2021-10-04_23-22-45z.3294samp.png b/scenes/cornell.2021-10-04_23-22-45z.3294samp.png
new file mode 100644
index 00000000..ee42cab4
Binary files /dev/null and b/scenes/cornell.2021-10-04_23-22-45z.3294samp.png differ
diff --git a/scenes/cornell.2021-10-05_01-11-01z.5000samp.png b/scenes/cornell.2021-10-05_01-11-01z.5000samp.png
new file mode 100644
index 00000000..e5d03b70
Binary files /dev/null and b/scenes/cornell.2021-10-05_01-11-01z.5000samp.png differ
diff --git a/scenes/deer.txt b/scenes/deer.txt
new file mode 100644
index 00000000..9e7898b2
--- /dev/null
+++ b/scenes/deer.txt
@@ -0,0 +1,219 @@
+// Emissive material (light)
+MATERIAL 0
+RGB 0.965, 0.933, 0.835
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 100
+
+// Diffuse white
+MATERIAL 1
+RGB 0.933, 0.788, 0.612
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// Diffuse navy blue
+MATERIAL 2
+RGB 0.039, 0.255, 0.345
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// Diffuse green
+MATERIAL 3
+RGB 0.004, 0.227, 0.125
+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
+
+// deer
+MATERIAL 5
+RGB 0.98, 0.91, 0.878
+SPECEX 0
+SPECRGB 1, 0.761, 0.78
+REFL 0.1
+REFR 0.8
+REFRIOR 1.2
+EMITTANCE 0
+
+// Diffuse orange
+MATERIAL 6
+RGB 0.38, 0.239, 0.035
+SPECEX 0
+SPECRGB 0.788, 0.71, 0.565
+REFL 0.5
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// cloud
+MATERIAL 7
+RGB 0.847, 0.949, 1
+SPECEX 0
+SPECRGB 0.847, 0.949, 1
+REFL 0
+REFR 0.2
+REFRIOR 1
+EMITTANCE 0
+
+// rock
+MATERIAL 8
+RGB 0.404, 0.404, 0.404
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// grass
+MATERIAL 9
+RGB 0.004, 0.227, 0.125
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// Camera
+CAMERA
+RES 740 400
+FOVY 37
+ITERATIONS 5000
+DEPTH 10
+FILE cornell
+EYE 2 5 11
+LOOKAT 0 5 0
+UP 0 1 0
+
+
+// moon
+OBJECT 0
+sphere
+material 0
+TRANS -5 10 9
+ROTAT 0 0 0
+SCALE 3 3 3
+
+// Floor
+OBJECT 1
+cube
+material 1
+TRANS 0 0 0
+ROTAT 0 0 0
+SCALE 30 .01 30
+
+
+// wall 0
+OBJECT 2
+cube
+material 3
+TRANS 10 10 0
+ROTAT 0 90 0
+SCALE 20 20 0.1
+
+// wall 1
+OBJECT 3
+cube
+material 3
+TRANS -10 10 0
+ROTAT 0 90 0
+SCALE 20 20 0.1
+
+// wall 2
+OBJECT 4
+cube
+material 2
+TRANS 0 10 -10
+ROTAT 0 0 0
+SCALE 20 20 0.1
+
+// wall 3
+OBJECT 5
+cube
+material 2
+TRANS 0 10 13
+ROTAT 0 0 0
+SCALE 20 20 0.1
+
+// wall 4
+OBJECT 4
+cube
+material 2
+TRANS 0 10 -10
+ROTAT 0 0 0
+SCALE 20 20 0.1
+
+// wall 5
+OBJECT 4
+cube
+material 6
+TRANS 10 5 -3
+ROTAT 0 -45 0
+SCALE 12 15 0.1
+
+// wall 6
+OBJECT 4
+cube
+material 6
+TRANS -10 5 -3
+ROTAT 0 45 0
+SCALE 12 15 0.1
+
+
+
+OBJECT 5
+mesh ./cloud1.obj
+material 7
+TRANS -5 8 0
+ROTAT 0 0 0
+SCALE 0.5 0.3 0.5
+
+
+OBJECT 5
+mesh ./rock.obj
+material 8
+TRANS 10.5 -7 -7
+ROTAT 0 0 0
+SCALE 1 1 1
+
+OBJECT 5
+mesh ./grass.obj
+material 9
+TRANS 4 0 -2
+ROTAT 0 0 0
+SCALE 3 3 3
+
+
+OBJECT 5
+mesh ./deer.obj
+material 5
+TRANS -1 0 2
+ROTAT 0 -30 0
+SCALE 1.2 1.2 1.2
+
+
+
diff --git a/scenes/depth.txt b/scenes/depth.txt
new file mode 100644
index 00000000..a8c61f4d
--- /dev/null
+++ b/scenes/depth.txt
@@ -0,0 +1,226 @@
+// Emissive material (light)
+MATERIAL 0
+RGB 0.965, 0.933, 0.835
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 70
+
+// Diffuse white
+MATERIAL 1
+RGB 0.933, 0.788, 0.612
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// Diffuse navy blue
+MATERIAL 2
+RGB 0.039, 0.255, 0.345
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// Diffuse green
+MATERIAL 3
+RGB 0.004, 0.227, 0.125
+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
+
+// Refractive white
+MATERIAL 5
+RGB 0.9 0.9 0.9
+SPECEX 0
+SPECRGB 1 1 1
+REFL 0.2
+REFR 0.4
+REFRIOR 1.2
+EMITTANCE 0
+
+// Diffuse orange
+MATERIAL 6
+RGB 0.38, 0.239, 0.035
+SPECEX 0
+SPECRGB 0.788, 0.71, 0.565
+REFL 0.5
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// tree
+MATERIAL 7
+RGB 0.004, 0.227, 0.125
+SPECEX 0
+SPECRGB 1, 1, 1
+REFL 0.1
+REFR 0.2
+REFRIOR 1
+EMITTANCE 0
+
+// rock
+MATERIAL 8
+RGB 0.404, 0.404, 0.404
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// grass
+MATERIAL 9
+RGB 0.004, 0.227, 0.125
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+
+// 1850 1000
+// Camera
+CAMERA
+RES 740 400
+FOVY 40
+ITERATIONS 5000
+DEPTH 10
+FILE cornell
+EYE 0 5 12
+LOOKAT 0 5 0
+UP 0 1 0
+APERTURE 0.15
+FOCUS_DIST 5.0
+// FOCUS_DIST 12.0
+// APERTURE 0.3
+
+
+// moon
+OBJECT 0
+sphere
+material 0
+TRANS -5 15 3
+ROTAT 0 0 0
+SCALE 3 3 3
+
+// Floor
+OBJECT 1
+cube
+material 1
+TRANS 0 0 0
+ROTAT 0 0 0
+SCALE 30 .01 30
+
+
+// wall 0
+OBJECT 2
+cube
+material 3
+TRANS 10 10 0
+ROTAT 0 90 0
+SCALE 20 20 0.1
+
+// wall 1
+OBJECT 3
+cube
+material 3
+TRANS -10 10 0
+ROTAT 0 90 0
+SCALE 20 20 0.1
+
+// wall 2
+OBJECT 4
+cube
+material 2
+TRANS 0 10 -10
+ROTAT 0 0 0
+SCALE 20 20 0.1
+
+// wall 3
+OBJECT 5
+cube
+material 1
+TRANS 0 10 13
+ROTAT 0 0 0
+SCALE 20 20 0.1
+
+// wall 4
+OBJECT 4
+cube
+material 2
+TRANS 0 10 -10
+ROTAT 0 0 0
+SCALE 20 20 0.1
+
+// wall 5
+OBJECT 4
+cube
+material 6
+TRANS 10 5 -3
+ROTAT 0 -45 0
+SCALE 12 15 0.1
+
+// wall 6
+OBJECT 4
+cube
+material 6
+TRANS -10 5 -3
+ROTAT 0 45 0
+SCALE 12 15 0.1
+
+
+OBJECT 5
+mesh ./rock.obj
+material 8
+TRANS 11.5 -7 -9
+ROTAT 0 0 0
+SCALE 1 1 1
+
+OBJECT 5
+mesh ./grass.obj
+material 9
+TRANS 5 0 -4
+ROTAT 0 0 0
+SCALE 3 3 3
+
+OBJECT 5
+mesh ./deer.obj
+material 5
+TRANS 0 0 0
+ROTAT 0 -30 0
+SCALE 1.2 1.2 1.2
+
+
+OBJECT 5
+mesh ./wolf.obj
+material 5
+TRANS -2.5 0 10
+ROTAT 0 155 0
+SCALE 1 1 1
+
+
+
+
+
+
diff --git a/scenes/mesh - Copy (2).txt b/scenes/mesh - Copy (2).txt
new file mode 100644
index 00000000..815500a8
--- /dev/null
+++ b/scenes/mesh - Copy (2).txt
@@ -0,0 +1,170 @@
+// Emissive material (light)
+MATERIAL 0
+RGB 1, 1, 1
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 100
+
+// Diffuse white
+MATERIAL 1
+RGB 0.933, 0.788, 0.612
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// Diffuse navy blue
+MATERIAL 2
+RGB 0.039, 0.255, 0.345
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// Diffuse green
+MATERIAL 3
+RGB 0.004, 0.227, 0.125
+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
+
+// Refractive white
+MATERIAL 5
+RGB 1 1 1
+SPECEX 0
+SPECRGB 1 1 1
+REFL 0.1
+REFR 0.9
+REFRIOR 1.2
+EMITTANCE 0
+
+// Diffuse orange
+MATERIAL 6
+RGB 0.38, 0.239, 0.035
+SPECEX 0
+SPECRGB 0.788, 0.71, 0.565
+REFL 0.5
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// Camera
+CAMERA
+RES 800 800
+FOVY 45
+ITERATIONS 5000
+DEPTH 5
+FILE cornell
+EYE 0.0 5 12.9
+LOOKAT 0 5 0
+UP 0 1 0
+
+
+// Ceiling light
+OBJECT 0
+sphere
+material 0
+TRANS -5 15 0
+ROTAT 0 0 0
+SCALE 2 2 2
+
+// Floor
+OBJECT 1
+cube
+material 1
+TRANS 0 0 0
+ROTAT 0 0 0
+SCALE 30 .01 30
+
+
+// wall 0
+OBJECT 2
+cube
+material 3
+TRANS 10 10 0
+ROTAT 0 90 0
+SCALE 20 20 0.1
+
+// wall 1
+OBJECT 3
+cube
+material 3
+TRANS -10 10 0
+ROTAT 0 90 0
+SCALE 20 20 0.1
+
+// wall 2
+OBJECT 4
+cube
+material 2
+TRANS 0 10 -10
+ROTAT 0 0 0
+SCALE 20 20 0.1
+
+// wall 3
+OBJECT 5
+cube
+material 2
+TRANS 0 10 13
+ROTAT 0 0 0
+SCALE 20 20 0.1
+
+// wall 4
+OBJECT 4
+cube
+material 2
+TRANS 0 10 -10
+ROTAT 0 0 0
+SCALE 20 20 0.1
+
+// wall 5
+OBJECT 4
+cube
+material 6
+TRANS 10 5 -3
+ROTAT 0 -45 0
+SCALE 12 15 0.1
+
+// wall 6
+OBJECT 4
+cube
+material 6
+TRANS -10 5 -3
+ROTAT 0 45 0
+SCALE 12 15 0.1
+
+
+
+OBJECT 5
+mesh ./cloud1.obj
+material 5
+TRANS -1 0 2
+ROTAT 0 45 0
+SCALE 1 1 1
+
+OBJECT 6
+mesh ./tree.obj
+material 5
+TRANS 2 0 -1
+ROTAT 0 0 0
+SCALE 1.8 1.8 1.8
diff --git a/scenes/mesh - Copy (3).txt b/scenes/mesh - Copy (3).txt
new file mode 100644
index 00000000..c53a8df9
--- /dev/null
+++ b/scenes/mesh - Copy (3).txt
@@ -0,0 +1,199 @@
+// Emissive material (light)
+MATERIAL 0
+RGB 0.965, 0.933, 0.835
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 100
+
+// Diffuse white
+MATERIAL 1
+RGB 0.933, 0.788, 0.612
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// Diffuse navy blue
+MATERIAL 2
+RGB 0.039, 0.255, 0.345
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// Diffuse green
+MATERIAL 3
+RGB 0.004, 0.227, 0.125
+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
+
+// Refractive white
+MATERIAL 5
+RGB 1 1 1
+SPECEX 0
+SPECRGB 1 1 1
+REFL 0.1
+REFR 0.9
+REFRIOR 1.2
+EMITTANCE 0
+
+// Diffuse orange
+MATERIAL 6
+RGB 0.38, 0.239, 0.035
+SPECEX 0
+SPECRGB 0.788, 0.71, 0.565
+REFL 0.5
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// cloud
+MATERIAL 7
+RGB 0.847, 0.949, 1
+SPECEX 0
+SPECRGB 0.847, 0.949, 1
+REFL 0
+REFR 0.2
+REFRIOR 1
+EMITTANCE 0
+
+// rock
+MATERIAL 8
+RGB 0.404, 0.404, 0.404
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// Camera
+CAMERA
+RES 800 800
+FOVY 45
+ITERATIONS 5000
+DEPTH 5
+FILE cornell
+EYE 2 0 12.9
+LOOKAT 0 5 0
+UP 0 1 0
+
+
+// moon
+OBJECT 0
+sphere
+material 0
+TRANS -5 15 10
+ROTAT 0 0 0
+SCALE 2 2 2
+
+// Floor
+OBJECT 1
+cube
+material 1
+TRANS 0 0 0
+ROTAT 0 0 0
+SCALE 30 .01 30
+
+
+// wall 0
+OBJECT 2
+cube
+material 3
+TRANS 10 10 0
+ROTAT 0 90 0
+SCALE 20 20 0.1
+
+// wall 1
+OBJECT 3
+cube
+material 3
+TRANS -10 10 0
+ROTAT 0 90 0
+SCALE 20 20 0.1
+
+// wall 2
+OBJECT 4
+cube
+material 2
+TRANS 0 10 -10
+ROTAT 0 0 0
+SCALE 20 20 0.1
+
+// wall 3
+OBJECT 5
+cube
+material 2
+TRANS 0 10 13
+ROTAT 0 0 0
+SCALE 20 20 0.1
+
+// wall 4
+OBJECT 4
+cube
+material 2
+TRANS 0 10 -10
+ROTAT 0 0 0
+SCALE 20 20 0.1
+
+// wall 5
+OBJECT 4
+cube
+material 6
+TRANS 10 5 -3
+ROTAT 0 -45 0
+SCALE 12 15 0.1
+
+// wall 6
+OBJECT 4
+cube
+material 6
+TRANS -10 5 -3
+ROTAT 0 45 0
+SCALE 12 15 0.1
+
+
+OBJECT 5
+mesh ./cloud1.obj
+material 7
+TRANS -5 8 0
+ROTAT 0 0 0
+SCALE 0.5 0.3 0.5
+
+OBJECT 5
+mesh ./deer.obj
+material 5
+TRANS -1 0 2
+ROTAT 0 -45 0
+SCALE 1.2 1.2 1.2
+
+
+OBJECT 5
+mesh ./rock.obj
+material 8
+TRANS 10 -7 -8
+ROTAT 0 0 0
+SCALE 1 1 1
+
+
diff --git a/scenes/mesh - Copy.txt b/scenes/mesh - Copy.txt
new file mode 100644
index 00000000..194500db
--- /dev/null
+++ b/scenes/mesh - Copy.txt
@@ -0,0 +1,137 @@
+// 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 0.894, 0.843, 0.816
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// Diffuse blue
+MATERIAL 2
+RGB 0.039, 0.255, 0.345
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// Diffuse orange
+MATERIAL 3
+RGB 1, 0.588, 0.212
+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
+
+// Refractive white
+MATERIAL 5
+RGB 1 1 1
+SPECEX 0
+SPECRGB 1 1 1
+REFL 0.1
+REFR 0.9
+REFRIOR 1.2
+EMITTANCE 0
+
+// Diffuse orange
+MATERIAL 6
+RGB .9 .9 .9
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// Camera
+CAMERA
+RES 800 800
+FOVY 45
+ITERATIONS 5000
+DEPTH 5
+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 5 .3 5
+
+// Floor
+OBJECT 1
+cube
+material 1
+TRANS 0 0 0
+ROTAT 0 0 0
+SCALE 20 .01 20
+
+// Ceiling
+OBJECT 2
+cube
+material 1
+TRANS 0 10 0
+ROTAT 0 0 90
+SCALE .01 20 20
+
+// wall 0
+OBJECT 3
+cube
+material 3
+TRANS 5 0 0
+ROTAT 0 90 0
+SCALE 20 20 0.1
+
+// wall 1
+OBJECT 4
+cube
+material 3
+TRANS -5 0 0
+ROTAT 0 90 0
+SCALE 20 20 0.1
+
+// wall 2
+OBJECT 5
+cube
+material 2
+TRANS 0 0 -5
+ROTAT 0 0 0
+SCALE 20 20 0.1
+
+OBJECT 6
+mesh ./wolf1.obj
+material 5
+TRANS 0 0 0
+ROTAT 0 45 0
+SCALE 1 1 1
+
diff --git a/scenes/mesh.txt b/scenes/mesh.txt
new file mode 100644
index 00000000..9a458ab6
--- /dev/null
+++ b/scenes/mesh.txt
@@ -0,0 +1,217 @@
+// Emissive material (light)
+MATERIAL 0
+RGB 0.965, 0.933, 0.835
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 80
+
+// Diffuse white
+MATERIAL 1
+RGB 0.933, 0.788, 0.612
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// Diffuse navy blue
+MATERIAL 2
+RGB 0.039, 0.255, 0.345
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// Diffuse green
+MATERIAL 3
+RGB 0.004, 0.227, 0.125
+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
+
+// Refractive white
+MATERIAL 5
+RGB 1 1 1
+SPECEX 0
+SPECRGB 1 1 1
+REFL 0.1
+REFR 0.9
+REFRIOR 1.2
+EMITTANCE 0
+
+// Diffuse orange
+MATERIAL 6
+RGB 0.38, 0.239, 0.035
+SPECEX 0
+SPECRGB 0.788, 0.71, 0.565
+REFL 0.5
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// cloud
+MATERIAL 7
+RGB 0.847, 0.949, 1
+SPECEX 0
+SPECRGB 0.847, 0.949, 1
+REFL 0
+REFR 0.2
+REFRIOR 1
+EMITTANCE 0
+
+// rock
+MATERIAL 8
+RGB 0.404, 0.404, 0.404
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// grass
+MATERIAL 9
+RGB 0.004, 0.227, 0.125
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// Camera
+CAMERA
+RES 800 800
+FOVY 45
+ITERATIONS 5000
+DEPTH 5
+FILE cornell
+EYE 2 6 12
+LOOKAT 0 5 0
+UP 0 1 0
+
+
+// moon
+OBJECT 0
+sphere
+material 0
+TRANS -5 12 9
+ROTAT 0 0 0
+SCALE 2 2 2
+
+// Floor
+OBJECT 1
+cube
+material 1
+TRANS 0 0 0
+ROTAT 0 0 0
+SCALE 30 .01 30
+
+
+// wall 0
+OBJECT 2
+cube
+material 3
+TRANS 10 10 0
+ROTAT 0 90 0
+SCALE 20 20 0.1
+
+// wall 1
+OBJECT 3
+cube
+material 3
+TRANS -10 10 0
+ROTAT 0 90 0
+SCALE 20 20 0.1
+
+// wall 2
+OBJECT 4
+cube
+material 2
+TRANS 0 10 -10
+ROTAT 0 0 0
+SCALE 20 20 0.1
+
+// wall 3
+OBJECT 5
+cube
+material 2
+TRANS 0 10 13
+ROTAT 0 0 0
+SCALE 20 20 0.1
+
+// wall 4
+OBJECT 4
+cube
+material 2
+TRANS 0 10 -10
+ROTAT 0 0 0
+SCALE 20 20 0.1
+
+// wall 5
+OBJECT 4
+cube
+material 6
+TRANS 10 5 -3
+ROTAT 0 -45 0
+SCALE 12 15 0.1
+
+// wall 6
+OBJECT 4
+cube
+material 6
+TRANS -10 5 -3
+ROTAT 0 45 0
+SCALE 12 15 0.1
+
+
+
+
+OBJECT 5
+mesh ./cloud1.obj
+material 7
+TRANS -5 8 0
+ROTAT 0 0 0
+SCALE 0.5 0.3 0.5
+
+OBJECT 5
+mesh ./deer.obj
+material 5
+TRANS -1 0 2
+ROTAT 0 -45 0
+SCALE 1.2 1.2 1.2
+
+OBJECT 5
+mesh ./rock.obj
+material 8
+TRANS 10.5 -7 -7
+ROTAT 0 0 0
+SCALE 1 1 1
+
+OBJECT 5
+mesh ./grass.obj
+material 9
+TRANS 4 0 -2
+ROTAT 0 0 0
+SCALE 3 3 3
+
+
diff --git a/scenes/mesh2.txt b/scenes/mesh2.txt
new file mode 100644
index 00000000..b3f73eb9
--- /dev/null
+++ b/scenes/mesh2.txt
@@ -0,0 +1,137 @@
+// Emissive material (light)
+MATERIAL 0
+RGB 1, 1, 1
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 70
+
+// Diffuse white
+MATERIAL 1
+RGB 0.894, 0.843, 0.816
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// Diffuse blue
+MATERIAL 2
+RGB 0.039, 0.255, 0.345
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// Diffuse orange
+MATERIAL 3
+RGB 1, 0.588, 0.212
+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
+
+// Refractive white
+MATERIAL 5
+RGB 1 1 1
+SPECEX 0
+SPECRGB 1 1 1
+REFL 0.1
+REFR 0.9
+REFRIOR 1.2
+EMITTANCE 0
+
+// Diffuse orange
+MATERIAL 6
+RGB .9 .9 .9
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// Camera
+CAMERA
+RES 800 800
+FOVY 45
+ITERATIONS 5000
+DEPTH 5
+FILE cornell
+EYE 0.0 5 10.5
+LOOKAT 0 5 0
+UP 0 1 0
+
+
+// Ceiling light
+OBJECT 0
+sphere
+material 0
+TRANS 0 10 0
+ROTAT 0 0 0
+SCALE 1 1 1
+
+// Floor
+OBJECT 1
+cube
+material 1
+TRANS 0 0 0
+ROTAT 0 0 0
+SCALE 20 .01 20
+
+
+// wall 0
+OBJECT 2
+cube
+material 3
+TRANS 7 0 0
+ROTAT 0 90 0
+SCALE 20 20 0.1
+
+// wall 1
+OBJECT 3
+cube
+material 3
+TRANS -7 0 0
+ROTAT 0 90 0
+SCALE 20 20 0.1
+
+// wall 2
+OBJECT 4
+cube
+material 2
+TRANS 0 0 -7
+ROTAT 0 0 0
+SCALE 20 20 0.1
+
+
+OBJECT 5
+mesh ./wolf.obj
+material 5
+TRANS -1 0 2
+ROTAT 0 45 0
+SCALE 1 1 1
+
+OBJECT 6
+mesh ./tree.obj
+material 5
+TRANS 2 0 -1
+ROTAT 0 0 0
+SCALE 1.8 1.8 1.8
diff --git a/scenes/refra.txt b/scenes/refra.txt
new file mode 100644
index 00000000..fc840c72
--- /dev/null
+++ b/scenes/refra.txt
@@ -0,0 +1,145 @@
+// Emissive material (light)
+MATERIAL 0
+RGB 1 1 1
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 3
+
+// 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
+
+// Refractive white
+MATERIAL 5
+RGB .98 .98 .98
+SPECEX 0
+SPECRGB .98 .98 .98
+REFL 0
+REFR 1
+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 5 .3 5
+
+// 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 2 -1
+ROTAT 0 0 0
+SCALE 3 3 3
+
+OBJECT 7
+sphere
+material 1
+TRANS -1 5 -1
+ROTAT 0 0 0
+SCALE 3 3 3
+
+OBJECT 8
+sphere
+material 5
+TRANS 2 5 -1
+ROTAT 0 0 0
+SCALE 3 3 3
+
diff --git a/scenes/refra2.txt b/scenes/refra2.txt
new file mode 100644
index 00000000..32a50fc2
--- /dev/null
+++ b/scenes/refra2.txt
@@ -0,0 +1,139 @@
+// Emissive material (light)
+MATERIAL 0
+RGB 1 1 1
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 8
+
+// 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
+
+// Refractive white
+MATERIAL 5
+RGB .98 .98 .98
+SPECEX 0
+SPECRGB .98 .98 .98
+REFL 0
+REFR 1
+REFRIOR 1.5
+EMITTANCE 0
+
+
+
+
+// Camera
+CAMERA
+RES 800 800
+FOVY 45
+ITERATIONS 5000
+DEPTH 8
+FILE cornell
+EYE 0.0 5 8
+LOOKAT 0 5 0
+UP 0 1 0
+APERTURE 0.05
+FOCUS_DIST 5.0
+
+
+// Ceiling light
+OBJECT 0
+cube
+material 0
+TRANS 0 10 0
+ROTAT 0 0 0
+SCALE 5 .3 5
+
+// 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
+
+// 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 1
+TRANS 0 2 -3
+ROTAT 0 0 0
+SCALE 3 3 3
+
+OBJECT 7
+sphere
+material 1
+TRANS 0 2 0
+ROTAT 0 0 0
+SCALE 3 3 3
+
+OBJECT 8
+sphere
+material 1
+TRANS 0 2 3
+ROTAT 0 0 0
+SCALE 3 3 3
+
diff --git a/scenes/wolf.txt b/scenes/wolf.txt
new file mode 100644
index 00000000..7c5669d9
--- /dev/null
+++ b/scenes/wolf.txt
@@ -0,0 +1,202 @@
+// Emissive material (light)
+MATERIAL 0
+RGB 0.965, 0.933, 0.835
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 150
+
+// Diffuse white
+MATERIAL 1
+RGB 0.933, 0.788, 0.612
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// Diffuse navy blue
+MATERIAL 2
+RGB 0.039, 0.255, 0.345
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// Diffuse green
+MATERIAL 3
+RGB 0.004, 0.227, 0.125
+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
+
+// Refractive white
+MATERIAL 5
+RGB 0.9 0.9 0.9
+SPECEX 0
+SPECRGB 1 1 1
+REFL 0.1
+REFR 0.8
+REFRIOR 1.2
+EMITTANCE 0
+
+// Diffuse orange
+MATERIAL 6
+RGB 0.38, 0.239, 0.035
+SPECEX 0
+SPECRGB 0.788, 0.71, 0.565
+REFL 0.5
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// tree
+MATERIAL 7
+RGB 0.004, 0.227, 0.125
+SPECEX 0
+SPECRGB 1, 1, 1
+REFL 0.1
+REFR 0.2
+REFRIOR 1
+EMITTANCE 0
+
+// rock
+MATERIAL 8
+RGB 0.404, 0.404, 0.404
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+// grass
+MATERIAL 9
+RGB 0.004, 0.227, 0.125
+SPECEX 0
+SPECRGB 0 0 0
+REFL 0
+REFR 0
+REFRIOR 0
+EMITTANCE 0
+
+
+// 1850 1000
+// Camera
+CAMERA
+RES 740 400
+FOVY 35
+ITERATIONS 5000
+DEPTH 10
+FILE cornell
+EYE 2 5 12
+LOOKAT 0 5 0
+UP 0 1 0
+
+
+// moon
+OBJECT 0
+sphere
+material 0
+TRANS -5 15 5
+ROTAT 0 0 0
+SCALE 2 2 2
+
+// Floor
+OBJECT 1
+cube
+material 1
+TRANS 0 0 0
+ROTAT 0 0 0
+SCALE 30 .01 30
+
+
+// wall 0
+OBJECT 2
+cube
+material 3
+TRANS 10 10 0
+ROTAT 0 90 0
+SCALE 20 20 0.1
+
+// wall 1
+OBJECT 3
+cube
+material 3
+TRANS -10 10 0
+ROTAT 0 90 0
+SCALE 20 20 0.1
+
+// wall 2
+OBJECT 4
+cube
+material 2
+TRANS 0 10 -10
+ROTAT 0 0 0
+SCALE 20 20 0.1
+
+// wall 3
+OBJECT 5
+cube
+material 2
+TRANS 0 10 13
+ROTAT 0 0 0
+SCALE 20 20 0.1
+
+// wall 4
+OBJECT 4
+cube
+material 2
+TRANS 0 10 -10
+ROTAT 0 0 0
+SCALE 20 20 0.1
+
+// wall 5
+OBJECT 4
+cube
+material 6
+TRANS 10 5 -3
+ROTAT 0 -45 0
+SCALE 12 15 0.1
+
+// wall 6
+OBJECT 4
+cube
+material 6
+TRANS -10 5 -3
+ROTAT 0 45 0
+SCALE 12 15 0.1
+
+OBJECT 5
+mesh ./wolf.obj
+material 5
+TRANS -1.5 0 2
+ROTAT 0 45 0
+SCALE 1 1 1
+
+OBJECT 6
+mesh ./lowpolytree.obj
+material 7
+TRANS 3 5 -1
+ROTAT 0 0 0
+SCALE 2.2 2.5 2.2
+
+
diff --git a/src/interactions.h b/src/interactions.h
index f969e458..309abaf8 100644
--- a/src/interactions.h
+++ b/src/interactions.h
@@ -1,6 +1,7 @@
#pragma once
#include "intersections.h"
+#include
// CHECKITOUT
/**
@@ -9,7 +10,7 @@
*/
__host__ __device__
glm::vec3 calculateRandomDirectionInHemisphere(
- glm::vec3 normal, thrust::default_random_engine &rng) {
+ glm::vec3 normal, thrust::default_random_engine& rng) {
thrust::uniform_real_distribution u01(0, 1);
float up = sqrt(u01(rng)); // cos(theta)
@@ -24,9 +25,11 @@ glm::vec3 calculateRandomDirectionInHemisphere(
glm::vec3 directionNotNormal;
if (abs(normal.x) < SQRT_OF_ONE_THIRD) {
directionNotNormal = glm::vec3(1, 0, 0);
- } else if (abs(normal.y) < SQRT_OF_ONE_THIRD) {
+ }
+ else if (abs(normal.y) < SQRT_OF_ONE_THIRD) {
directionNotNormal = glm::vec3(0, 1, 0);
- } else {
+ }
+ else {
directionNotNormal = glm::vec3(0, 0, 1);
}
@@ -41,6 +44,14 @@ glm::vec3 calculateRandomDirectionInHemisphere(
+ sin(around) * over * perpendicularDirection2;
}
+__device__ glm::vec3 random_spherical(thrust::default_random_engine& rng) {
+ thrust::uniform_real_distribution u01(-1, 1);
+ thrust::uniform_real_distribution u03(-1, 1);
+ thrust::uniform_real_distribution u02(-1, 1);
+ glm::vec3 random_vec = glm::normalize(glm::vec3(u01(rng), u02(rng), u03(rng)));
+ return random_vec;
+}
+
/**
* Scatter a ray with some probabilities according to the material properties.
* For example, a diffuse surface scatters in a cosine-weighted hemisphere.
@@ -66,14 +77,69 @@ glm::vec3 calculateRandomDirectionInHemisphere(
*
* You may need to change the parameter list for your purposes!
*/
+__host__ __device__ float reflectance(float cosine, float ref_idx) {
+ // Use Schlick's approximation for reflectance.
+ float r0 = powf((1.f - ref_idx) / (1.0f + ref_idx), 2.0f);
+ return r0 + (1.f - r0) * powf((1.0f - cosine), 5.0f);
+}
+
__host__ __device__
void scatterRay(
- PathSegment & pathSegment,
- glm::vec3 intersect,
- 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.
+ PathSegment& pathSegment,
+ glm::vec3 intersect,
+ glm::vec3 normal,
+ const Material& m,
+ thrust::default_random_engine& rng) {
+ thrust::uniform_real_distribution u01(0, 1);
+ float random_num = u01(rng);
+ if (m.hasReflective > random_num){
+ pathSegment.ray.direction = glm::reflect(pathSegment.ray.direction, normal);
+ pathSegment.ray.origin = intersect + EPSILON * normal;
+ pathSegment.color *= m.specular.color;
+ pathSegment.color = glm::clamp(pathSegment.color, glm::vec3(0.0f), glm::vec3(1.0f));
+ }
+ else if (m.hasRefractive > random_num) {
+ glm::vec3 ray_direction = glm::normalize(pathSegment.ray.direction);
+ bool from_inside = glm::dot(ray_direction, normal) > 0.0f;
+ glm::vec3 refract_ray_direction;
+ float refraction_ratio = m.indexOfRefraction;
+ if (from_inside) {
+ normal = glm::normalize(-1.0f * normal);
+ refract_ray_direction = glm::normalize(glm::refract(pathSegment.ray.direction, normal, m.indexOfRefraction));
+ }
+ else {
+ refraction_ratio = 1.0f / m.indexOfRefraction;
+ refract_ray_direction = glm::normalize(glm::refract(pathSegment.ray.direction, normal, 1.0f / m.indexOfRefraction));
+ }
+ float cos_theta = fmin(glm::dot(-ray_direction, normal), 1.0f);
+ float sin_theta = sqrt(1.0f - cos_theta * cos_theta);
+ bool cannot_refract = (refraction_ratio * sin_theta) > 1.0;
+
+ if (cannot_refract || reflectance(cos_theta, refraction_ratio) > random_num) {
+ pathSegment.ray.direction = glm::reflect(pathSegment.ray.direction, normal);
+ pathSegment.ray.origin = intersect + EPSILON * normal;;
+ pathSegment.color *= m.specular.color;
+ }
+ else {
+ pathSegment.ray.direction = refract_ray_direction;
+ pathSegment.ray.origin = intersect + 0.001f * refract_ray_direction;
+ pathSegment.color *= m.specular.color;
+ }
+ }
+ else {
+ // my implementation
+ //glm::vec3 random_vec = random_spherical(rng);
+ //pathSegments.ray.direction = glm::normalize(normal + random_vec);
+ pathSegment.ray.direction = glm::normalize(calculateRandomDirectionInHemisphere(normal, rng));
+ pathSegment.ray.origin = intersect + EPSILON * normal;
+ pathSegment.color *= m.color;
+ pathSegment.color = glm::clamp(pathSegment.color, glm::vec3(0.0f), glm::vec3(1.0f));
+
+ }
+ pathSegment.remainingBounces--;
+ pathSegment.color = glm::clamp(pathSegment.color, glm::vec3(0.0f), glm::vec3(1.0f));
+
+
+
+
}
diff --git a/src/intersections.h b/src/intersections.h
index b1504071..7d8894a4 100644
--- a/src/intersections.h
+++ b/src/intersections.h
@@ -142,3 +142,37 @@ __host__ __device__ float sphereIntersectionTest(Geom sphere, Ray r,
return glm::length(r.origin - intersectionPoint);
}
+
+__host__ __device__ float triangleIntersectionTest(Geom geom, Ray r,
+ glm::vec3& intersectionPoint, glm::vec3& normal, bool& outside) {
+ glm::vec3 bary_position;
+ Triangle tri = geom.triangle;
+ bool hit = glm::intersectRayTriangle(r.origin, r.direction,
+ tri.vertex[0],
+ tri.vertex[1],
+ tri.vertex[2], bary_position);
+ //glm::vec3 bary_position_reverse; // glm intersectRayTriangle ignores back hitting.
+ //bool hit_reverse = glm::intersectRayTriangle(r.origin, r.direction,
+ // tri.vertex[0],
+ // tri.vertex[2],
+ // tri.vertex[1], bary_position_reverse);
+
+ if (hit) {
+ normal = (tri.normals[0] * (1.0f - bary_position.x - bary_position.y)) +
+ (tri.normals[1] * bary_position.x) + (tri.normals[2] * bary_position.y);
+ outside = false;
+ }
+ //else if (hit_reverse) {
+ // normal = -1.0f * (tri.normals[0] * (1.0f - bary_position_reverse.x - bary_position_reverse.y)) +
+ // (tri.normals[1] * bary_position_reverse.x) + (tri.normals[2] * bary_position_reverse.y);
+ // outside = true;
+ //}
+ else {
+ return -1;
+ }
+ float t = bary_position.z;
+ intersectionPoint = getPointOnRay(r, t);
+
+ return t;
+}
+
diff --git a/src/loader_example.cc b/src/loader_example.cc
new file mode 100644
index 00000000..8143bb79
--- /dev/null
+++ b/src/loader_example.cc
@@ -0,0 +1,437 @@
+//
+// g++ loader_example.cc
+//
+#define TINYOBJLOADER_IMPLEMENTATION
+#include "tiny_obj_loader.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef _WIN32
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include
+#include
+#ifdef __cplusplus
+}
+#endif
+#pragma comment(lib, "winmm.lib")
+#else
+#if defined(__unix__) || defined(__APPLE__)
+#include
+#else
+#include
+#endif
+#endif
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#if __has_warning("-Wzero-as-null-pointer-constant")
+#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
+#endif
+#endif
+
+class timerutil {
+ public:
+#ifdef _WIN32
+ typedef DWORD time_t;
+
+ timerutil() { ::timeBeginPeriod(1); }
+ ~timerutil() { ::timeEndPeriod(1); }
+
+ void start() { t_[0] = ::timeGetTime(); }
+ void end() { t_[1] = ::timeGetTime(); }
+
+ time_t sec() { return (time_t)((t_[1] - t_[0]) / 1000); }
+ time_t msec() { return (time_t)((t_[1] - t_[0])); }
+ time_t usec() { return (time_t)((t_[1] - t_[0]) * 1000); }
+ time_t current() { return ::timeGetTime(); }
+
+#else
+#if defined(__unix__) || defined(__APPLE__)
+ typedef unsigned long int time_t;
+
+ void start() { gettimeofday(tv + 0, &tz); }
+ void end() { gettimeofday(tv + 1, &tz); }
+
+ time_t sec() { return static_cast(tv[1].tv_sec - tv[0].tv_sec); }
+ time_t msec() {
+ return this->sec() * 1000 +
+ static_cast((tv[1].tv_usec - tv[0].tv_usec) / 1000);
+ }
+ time_t usec() {
+ return this->sec() * 1000000 +
+ static_cast(tv[1].tv_usec - tv[0].tv_usec);
+ }
+ time_t current() {
+ struct timeval t;
+ gettimeofday(&t, NULL);
+ return static_cast(t.tv_sec * 1000 + t.tv_usec);
+ }
+
+#else // C timer
+ // using namespace std;
+ typedef clock_t time_t;
+
+ void start() { t_[0] = clock(); }
+ void end() { t_[1] = clock(); }
+
+ time_t sec() { return (time_t)((t_[1] - t_[0]) / CLOCKS_PER_SEC); }
+ time_t msec() { return (time_t)((t_[1] - t_[0]) * 1000 / CLOCKS_PER_SEC); }
+ time_t usec() { return (time_t)((t_[1] - t_[0]) * 1000000 / CLOCKS_PER_SEC); }
+ time_t current() { return (time_t)clock(); }
+
+#endif
+#endif
+
+ private:
+#ifdef _WIN32
+ DWORD t_[2];
+#else
+#if defined(__unix__) || defined(__APPLE__)
+ struct timeval tv[2];
+ struct timezone tz;
+#else
+ time_t t_[2];
+#endif
+#endif
+};
+
+static void PrintInfo(const tinyobj::attrib_t& attrib,
+ const std::vector& shapes,
+ const std::vector& materials) {
+ std::cout << "# of vertices : " << (attrib.vertices.size() / 3) << std::endl;
+ std::cout << "# of normals : " << (attrib.normals.size() / 3) << std::endl;
+ std::cout << "# of texcoords : " << (attrib.texcoords.size() / 2)
+ << std::endl;
+
+ std::cout << "# of shapes : " << shapes.size() << std::endl;
+ std::cout << "# of materials : " << materials.size() << std::endl;
+
+ for (size_t v = 0; v < attrib.vertices.size() / 3; v++) {
+ printf(" v[%ld] = (%f, %f, %f)\n", static_cast(v),
+ static_cast(attrib.vertices[3 * v + 0]),
+ static_cast(attrib.vertices[3 * v + 1]),
+ static_cast(attrib.vertices[3 * v + 2]));
+ }
+
+ for (size_t v = 0; v < attrib.normals.size() / 3; v++) {
+ printf(" n[%ld] = (%f, %f, %f)\n", static_cast(v),
+ static_cast(attrib.normals[3 * v + 0]),
+ static_cast(attrib.normals[3 * v + 1]),
+ static_cast(attrib.normals[3 * v + 2]));
+ }
+
+ for (size_t v = 0; v < attrib.texcoords.size() / 2; v++) {
+ printf(" uv[%ld] = (%f, %f)\n", static_cast(v),
+ static_cast(attrib.texcoords[2 * v + 0]),
+ static_cast(attrib.texcoords[2 * v + 1]));
+ }
+
+ // For each shape
+ for (size_t i = 0; i < shapes.size(); i++) {
+ printf("shape[%ld].name = %s\n", static_cast(i),
+ shapes[i].name.c_str());
+ printf("Size of shape[%ld].mesh.indices: %lu\n", static_cast(i),
+ static_cast(shapes[i].mesh.indices.size()));
+ printf("Size of shape[%ld].lines.indices: %lu\n", static_cast(i),
+ static_cast(shapes[i].lines.indices.size()));
+ printf("Size of shape[%ld].points.indices: %lu\n", static_cast(i),
+ static_cast(shapes[i].points.indices.size()));
+
+ size_t index_offset = 0;
+
+ assert(shapes[i].mesh.num_face_vertices.size() ==
+ shapes[i].mesh.material_ids.size());
+
+ assert(shapes[i].mesh.num_face_vertices.size() ==
+ shapes[i].mesh.smoothing_group_ids.size());
+
+ printf("shape[%ld].num_faces: %lu\n", static_cast(i),
+ static_cast(shapes[i].mesh.num_face_vertices.size()));
+
+ // For each face
+ for (size_t f = 0; f < shapes[i].mesh.num_face_vertices.size(); f++) {
+ size_t fnum = shapes[i].mesh.num_face_vertices[f];
+
+ printf(" face[%ld].fnum = %ld\n", static_cast(f),
+ static_cast(fnum));
+
+ // For each vertex in the face
+ for (size_t v = 0; v < fnum; v++) {
+ tinyobj::index_t idx = shapes[i].mesh.indices[index_offset + v];
+ printf(" face[%ld].v[%ld].idx = %d/%d/%d\n", static_cast(f),
+ static_cast(v), idx.vertex_index, idx.normal_index,
+ idx.texcoord_index);
+ }
+
+ printf(" face[%ld].material_id = %d\n", static_cast(f),
+ shapes[i].mesh.material_ids[f]);
+ printf(" face[%ld].smoothing_group_id = %d\n", static_cast(f),
+ shapes[i].mesh.smoothing_group_ids[f]);
+
+ index_offset += fnum;
+ }
+
+ printf("shape[%ld].num_tags: %lu\n", static_cast(i),
+ static_cast(shapes[i].mesh.tags.size()));
+ for (size_t t = 0; t < shapes[i].mesh.tags.size(); t++) {
+ printf(" tag[%ld] = %s ", static_cast(t),
+ shapes[i].mesh.tags[t].name.c_str());
+ printf(" ints: [");
+ for (size_t j = 0; j < shapes[i].mesh.tags[t].intValues.size(); ++j) {
+ printf("%ld", static_cast(shapes[i].mesh.tags[t].intValues[j]));
+ if (j < (shapes[i].mesh.tags[t].intValues.size() - 1)) {
+ printf(", ");
+ }
+ }
+ printf("]");
+
+ printf(" floats: [");
+ for (size_t j = 0; j < shapes[i].mesh.tags[t].floatValues.size(); ++j) {
+ printf("%f", static_cast(
+ shapes[i].mesh.tags[t].floatValues[j]));
+ if (j < (shapes[i].mesh.tags[t].floatValues.size() - 1)) {
+ printf(", ");
+ }
+ }
+ printf("]");
+
+ printf(" strings: [");
+ for (size_t j = 0; j < shapes[i].mesh.tags[t].stringValues.size(); ++j) {
+ printf("%s", shapes[i].mesh.tags[t].stringValues[j].c_str());
+ if (j < (shapes[i].mesh.tags[t].stringValues.size() - 1)) {
+ printf(", ");
+ }
+ }
+ printf("]");
+ printf("\n");
+ }
+ }
+
+ for (size_t i = 0; i < materials.size(); i++) {
+ printf("material[%ld].name = %s\n", static_cast(i),
+ materials[i].name.c_str());
+ printf(" material.Ka = (%f, %f ,%f)\n",
+ static_cast(materials[i].ambient[0]),
+ static_cast(materials[i].ambient[1]),
+ static_cast(materials[i].ambient[2]));
+ printf(" material.Kd = (%f, %f ,%f)\n",
+ static_cast(materials[i].diffuse[0]),
+ static_cast(materials[i].diffuse[1]),
+ static_cast(materials[i].diffuse[2]));
+ printf(" material.Ks = (%f, %f ,%f)\n",
+ static_cast(materials[i].specular[0]),
+ static_cast(materials[i].specular[1]),
+ static_cast(materials[i].specular[2]));
+ printf(" material.Tr = (%f, %f ,%f)\n",
+ static_cast(materials[i].transmittance[0]),
+ static_cast(materials[i].transmittance[1]),
+ static_cast(materials[i].transmittance[2]));
+ printf(" material.Ke = (%f, %f ,%f)\n",
+ static_cast(materials[i].emission[0]),
+ static_cast(materials[i].emission[1]),
+ static_cast(materials[i].emission[2]));
+ printf(" material.Ns = %f\n",
+ static_cast(materials[i].shininess));
+ printf(" material.Ni = %f\n", static_cast(materials[i].ior));
+ printf(" material.dissolve = %f\n",
+ static_cast(materials[i].dissolve));
+ printf(" material.illum = %d\n", materials[i].illum);
+ printf(" material.map_Ka = %s\n", materials[i].ambient_texname.c_str());
+ printf(" material.map_Kd = %s\n", materials[i].diffuse_texname.c_str());
+ printf(" material.map_Ks = %s\n", materials[i].specular_texname.c_str());
+ printf(" material.map_Ns = %s\n",
+ materials[i].specular_highlight_texname.c_str());
+ printf(" material.map_bump = %s\n", materials[i].bump_texname.c_str());
+ printf(" bump_multiplier = %f\n", static_cast(materials[i].bump_texopt.bump_multiplier));
+ printf(" material.map_d = %s\n", materials[i].alpha_texname.c_str());
+ printf(" material.disp = %s\n", materials[i].displacement_texname.c_str());
+ printf(" <>\n");
+ printf(" material.Pr = %f\n", static_cast(materials[i].roughness));
+ printf(" material.Pm = %f\n", static_cast(materials[i].metallic));
+ printf(" material.Ps = %f\n", static_cast(materials[i].sheen));
+ printf(" material.Pc = %f\n", static_cast(materials[i].clearcoat_thickness));
+ printf(" material.Pcr = %f\n", static_cast(materials[i].clearcoat_thickness));
+ printf(" material.aniso = %f\n", static_cast(materials[i].anisotropy));
+ printf(" material.anisor = %f\n", static_cast(materials[i].anisotropy_rotation));
+ printf(" material.map_Ke = %s\n", materials[i].emissive_texname.c_str());
+ printf(" material.map_Pr = %s\n", materials[i].roughness_texname.c_str());
+ printf(" material.map_Pm = %s\n", materials[i].metallic_texname.c_str());
+ printf(" material.map_Ps = %s\n", materials[i].sheen_texname.c_str());
+ printf(" material.norm = %s\n", materials[i].normal_texname.c_str());
+ std::map::const_iterator it(
+ materials[i].unknown_parameter.begin());
+ std::map::const_iterator itEnd(
+ materials[i].unknown_parameter.end());
+
+ for (; it != itEnd; it++) {
+ printf(" material.%s = %s\n", it->first.c_str(), it->second.c_str());
+ }
+ printf("\n");
+ }
+}
+
+static bool TestLoadObj(const char* filename, const char* basepath = NULL,
+ bool triangulate = true) {
+ std::cout << "Loading " << filename << std::endl;
+
+ tinyobj::attrib_t attrib;
+ std::vector shapes;
+ std::vector materials;
+
+ timerutil t;
+ t.start();
+ std::string warn;
+ std::string err;
+ bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, filename,
+ basepath, triangulate);
+ t.end();
+ printf("Parsing time: %lu [msecs]\n", t.msec());
+
+ if (!warn.empty()) {
+ std::cout << "WARN: " << warn << std::endl;
+ }
+
+ if (!err.empty()) {
+ std::cerr << "ERR: " << err << std::endl;
+ }
+
+ if (!ret) {
+ printf("Failed to load/parse .obj.\n");
+ return false;
+ }
+
+ PrintInfo(attrib, shapes, materials);
+
+ return true;
+}
+
+static bool TestStreamLoadObj() {
+ std::cout << "Stream Loading " << std::endl;
+
+ std::stringstream objStream;
+ objStream << "mtllib cube.mtl\n"
+ "\n"
+ "v 0.000000 2.000000 2.000000\n"
+ "v 0.000000 0.000000 2.000000\n"
+ "v 2.000000 0.000000 2.000000\n"
+ "v 2.000000 2.000000 2.000000\n"
+ "v 0.000000 2.000000 0.000000\n"
+ "v 0.000000 0.000000 0.000000\n"
+ "v 2.000000 0.000000 0.000000\n"
+ "v 2.000000 2.000000 0.000000\n"
+ "# 8 vertices\n"
+ "\n"
+ "g front cube\n"
+ "usemtl white\n"
+ "f 1 2 3 4\n"
+ "g back cube\n"
+ "# expects white material\n"
+ "f 8 7 6 5\n"
+ "g right cube\n"
+ "usemtl red\n"
+ "f 4 3 7 8\n"
+ "g top cube\n"
+ "usemtl white\n"
+ "f 5 1 4 8\n"
+ "g left cube\n"
+ "usemtl green\n"
+ "f 5 6 2 1\n"
+ "g bottom cube\n"
+ "usemtl white\n"
+ "f 2 6 7 3\n"
+ "# 6 elements";
+
+ std::string matStream(
+ "newmtl white\n"
+ "Ka 0 0 0\n"
+ "Kd 1 1 1\n"
+ "Ks 0 0 0\n"
+ "\n"
+ "newmtl red\n"
+ "Ka 0 0 0\n"
+ "Kd 1 0 0\n"
+ "Ks 0 0 0\n"
+ "\n"
+ "newmtl green\n"
+ "Ka 0 0 0\n"
+ "Kd 0 1 0\n"
+ "Ks 0 0 0\n"
+ "\n"
+ "newmtl blue\n"
+ "Ka 0 0 0\n"
+ "Kd 0 0 1\n"
+ "Ks 0 0 0\n"
+ "\n"
+ "newmtl light\n"
+ "Ka 20 20 20\n"
+ "Kd 1 1 1\n"
+ "Ks 0 0 0");
+
+ using namespace tinyobj;
+ class MaterialStringStreamReader : public MaterialReader {
+ public:
+ MaterialStringStreamReader(const std::string& matSStream)
+ : m_matSStream(matSStream) {}
+ virtual ~MaterialStringStreamReader() TINYOBJ_OVERRIDE {}
+ virtual bool operator()(const std::string& matId,
+ std::vector* materials,
+ std::map* matMap,
+ std::string* warn,
+ std::string* err) TINYOBJ_OVERRIDE {
+ (void)err;
+ (void)matId;
+ LoadMtl(matMap, materials, &m_matSStream, warn, err);
+
+ return true;
+ }
+
+ private:
+ std::stringstream m_matSStream;
+ };
+
+ MaterialStringStreamReader matSSReader(matStream);
+ tinyobj::attrib_t attrib;
+ std::vector shapes;
+ std::vector materials;
+ std::string warn;
+ std::string err;
+ bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, &objStream,
+ &matSSReader);
+
+ if (!err.empty()) {
+ std::cerr << err << std::endl;
+ }
+
+ if (!ret) {
+ return false;
+ }
+
+ PrintInfo(attrib, shapes, materials);
+
+ return true;
+}
+
+int main(int argc, char** argv) {
+ if (argc > 1) {
+ const char* basepath = "models/";
+ if (argc > 2) {
+ basepath = argv[2];
+ }
+ assert(true == TestLoadObj(argv[1], basepath));
+ } else {
+ // assert(true == TestLoadObj("cornell_box.obj"));
+ // assert(true == TestLoadObj("cube.obj"));
+ assert(true == TestStreamLoadObj());
+ assert(true ==
+ TestLoadObj("models/catmark_torus_creases0.obj", "models/", false));
+ }
+
+ return 0;
+}
diff --git a/src/main.cpp b/src/main.cpp
index fe8e85ec..45d873e4 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -38,7 +38,8 @@ int main(int argc, char** argv) {
return 1;
}
- const char *sceneFile = argv[1];
+ //const char* sceneFile = "mesh.txt";
+ const char* sceneFile = argv[1];
// Load scene file
scene = new Scene(sceneFile);
diff --git a/src/pathtrace.cu b/src/pathtrace.cu
index 056e1467..275e09b8 100644
--- a/src/pathtrace.cu
+++ b/src/pathtrace.cu
@@ -4,17 +4,25 @@
#include
#include
#include
+#include
+#include
+#include
#include "sceneStructs.h"
#include "scene.h"
#include "glm/glm.hpp"
#include "glm/gtx/norm.hpp"
+#include "glm/gtc/random.hpp"
#include "utilities.h"
#include "pathtrace.h"
#include "intersections.h"
#include "interactions.h"
#define ERRORCHECK 1
+#define SUB_PIXEL_SAMPLE 10
+#define USE_ANTIALIASING 1
+#define USE_MATERIAL_SORT 0
+#define USE_DEPTH_OF_FIELD 1
#define FILENAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
#define checkCUDAError(msg) checkCUDAErrorFn(msg, FILENAME, __LINE__)
@@ -73,6 +81,7 @@ static Geom * dev_geoms = NULL;
static Material * dev_materials = NULL;
static PathSegment * dev_paths = NULL;
static ShadeableIntersection * dev_intersections = NULL;
+static ShadeableIntersection* dev_intersections_cache = NULL;
// TODO: static variables for device memory, any extra info you need, etc
// ...
@@ -80,11 +89,12 @@ void pathtraceInit(Scene *scene) {
hst_scene = scene;
const Camera &cam = hst_scene->state.camera;
const int pixelcount = cam.resolution.x * cam.resolution.y;
+ const int pixelcount_sub = cam.resolution.x * cam.resolution.y * SUB_PIXEL_SAMPLE;
cudaMalloc(&dev_image, pixelcount * sizeof(glm::vec3));
cudaMemset(dev_image, 0, pixelcount * sizeof(glm::vec3));
- cudaMalloc(&dev_paths, pixelcount * sizeof(PathSegment));
+ cudaMalloc(&dev_paths, pixelcount_sub * sizeof(PathSegment));
cudaMalloc(&dev_geoms, scene->geoms.size() * sizeof(Geom));
cudaMemcpy(dev_geoms, scene->geoms.data(), scene->geoms.size() * sizeof(Geom), cudaMemcpyHostToDevice);
@@ -92,8 +102,11 @@ void pathtraceInit(Scene *scene) {
cudaMalloc(&dev_materials, scene->materials.size() * sizeof(Material));
cudaMemcpy(dev_materials, scene->materials.data(), scene->materials.size() * sizeof(Material), cudaMemcpyHostToDevice);
- cudaMalloc(&dev_intersections, pixelcount * sizeof(ShadeableIntersection));
- cudaMemset(dev_intersections, 0, pixelcount * sizeof(ShadeableIntersection));
+ cudaMalloc(&dev_intersections, pixelcount_sub * sizeof(ShadeableIntersection));
+ cudaMemset(dev_intersections, 0, pixelcount_sub * sizeof(ShadeableIntersection));
+
+ cudaMalloc(&dev_intersections_cache, pixelcount_sub * sizeof(ShadeableIntersection));
+ cudaMemset(dev_intersections_cache, 0, pixelcount_sub * sizeof(ShadeableIntersection));
// TODO: initialize any extra device memeory you need
@@ -106,6 +119,7 @@ void pathtraceFree() {
cudaFree(dev_geoms);
cudaFree(dev_materials);
cudaFree(dev_intersections);
+ cudaFree(dev_intersections_cache);
// TODO: clean up any extra device memory you created
checkCUDAError("pathtraceFree");
@@ -121,22 +135,47 @@ void pathtraceFree() {
*/
__global__ void generateRayFromCamera(Camera cam, int iter, int traceDepth, PathSegment* pathSegments)
{
+
int x = (blockIdx.x * blockDim.x) + threadIdx.x;
int y = (blockIdx.y * blockDim.y) + threadIdx.y;
+ int z = threadIdx.z;
if (x < cam.resolution.x && y < cam.resolution.y) {
int index = x + (y * cam.resolution.x);
- PathSegment & segment = pathSegments[index];
+ int index_sub = x + (y * cam.resolution.x) + z * cam.resolution.x * cam.resolution.y;
+ PathSegment & segment = pathSegments[index_sub];
+ thrust::default_random_engine rng = makeSeededRandomEngine(iter, index_sub, 0);
+ thrust::uniform_real_distribution u01(-1.0, 1.0);
+
+
segment.ray.origin = cam.position;
- segment.color = glm::vec3(1.0f, 1.0f, 1.0f);
+ segment.color = glm::vec3(1.0f, 1.0f, 1.0f);
// TODO: implement antialiasing by jittering the ray
- segment.ray.direction = glm::normalize(cam.view
- - cam.right * cam.pixelLength.x * ((float)x - (float)cam.resolution.x * 0.5f)
- - cam.up * cam.pixelLength.y * ((float)y - (float)cam.resolution.y * 0.5f)
+ #if USE_ANTIALIASING
+ segment.ray.direction = glm::normalize(cam.view
+ - cam.right * cam.pixelLength.x * ((float)x - (float)cam.resolution.x * 0.5f + u01(rng))
+ - cam.up * cam.pixelLength.y * ((float)y - (float)cam.resolution.y * 0.5f + u01(rng))
+ );
+ #else
+ segment.ray.direction = glm::normalize(cam.view
+ - cam.right * cam.pixelLength.x * ((float)x - (float)cam.resolution.x * 0.5f)
+ - cam.up * cam.pixelLength.y * ((float)y - (float)cam.resolution.y * 0.5f)
);
+ #endif
+
+ #if USE_DEPTH_OF_FIELD
+ // defouce blur
+ float focus_dist = cam.focus_dist;
+ float aperture_radius = cam.aperture;
+ glm::vec2 random_vec = glm::normalize(glm::vec2(u01(rng), u01(rng)));
+ glm::vec3 offset = cam.right * random_vec.x * aperture_radius + cam.up * random_vec.y * aperture_radius;
+ segment.ray.direction = glm::normalize(segment.ray.direction * focus_dist - offset);
+ segment.ray.origin += offset;
+ #endif
+ // TODO: implement antialiasing by jittering the ray
segment.pixelIndex = index;
segment.remainingBounces = traceDepth;
}
@@ -185,6 +224,10 @@ __global__ void computeIntersections(
{
t = sphereIntersectionTest(geom, pathSegment.ray, tmp_intersect, tmp_normal, outside);
}
+ else if (geom.type == TRIANGLE)
+ {
+ t = triangleIntersectionTest(geom, pathSegment.ray, tmp_intersect, tmp_normal, outside);
+ }
// TODO: add more intersection tests here... triangle? metaball? CSG?
// Compute the minimum t from the intersection tests to determine what
@@ -208,10 +251,13 @@ __global__ void computeIntersections(
intersections[path_index].t = t_min;
intersections[path_index].materialId = geoms[hit_geom_index].materialid;
intersections[path_index].surfaceNormal = normal;
+ intersections[path_index].intersect_point = intersect_point;
}
}
}
+
+
// LOOK: "fake" shader demonstrating what you might do with the info in
// a ShadeableIntersection, as well as how to use thrust's random number
// generator. Observe that since the thrust random number generator basically
@@ -221,7 +267,7 @@ __global__ void computeIntersections(
// Note that this shader does NOT do a BSDF evaluation!
// Your shaders should handle that - this can allow techniques such as
// bump mapping.
-__global__ void shadeFakeMaterial (
+__global__ void shadeMaterial (
int iter
, int num_paths
, ShadeableIntersection * shadeableIntersections
@@ -246,14 +292,13 @@ __global__ void shadeFakeMaterial (
// If the material indicates that the object was a light, "light" the ray
if (material.emittance > 0.0f) {
pathSegments[idx].color *= (materialColor * material.emittance);
+ pathSegments[idx].remainingBounces = 0;
}
// Otherwise, do some pseudo-lighting computation. This is actually more
// like what you would expect from shading in a rasterizer like OpenGL.
// TODO: replace this! you should be able to start with basically a one-liner
else {
- float lightTerm = glm::dot(intersection.surfaceNormal, glm::vec3(0.0f, 1.0f, 0.0f));
- pathSegments[idx].color *= (materialColor * lightTerm) * 0.3f + ((1.0f - intersection.t * 0.02f) * materialColor) * 0.7f;
- pathSegments[idx].color *= u01(rng); // apply some noise because why not
+ scatterRay(pathSegments[idx], intersection.intersect_point, intersection.surfaceNormal, material, rng);
}
// If there was no intersection, color the ray black.
// Lots of renderers use 4 channel color, RGBA, where A = alpha, often
@@ -261,6 +306,7 @@ __global__ void shadeFakeMaterial (
// This can be useful for post-processing and image compositing.
} else {
pathSegments[idx].color = glm::vec3(0.0f);
+ pathSegments[idx].remainingBounces = 0;
}
}
}
@@ -273,121 +319,169 @@ __global__ void finalGather(int nPaths, glm::vec3 * image, PathSegment * iterati
if (index < nPaths)
{
PathSegment iterationPath = iterationPaths[index];
- image[iterationPath.pixelIndex] += iterationPath.color;
+ image[iterationPath.pixelIndex] += iterationPath.color / (float)SUB_PIXEL_SAMPLE;
}
}
+struct sort_material_id{
+ __host__ __device__ bool operator()(const ShadeableIntersection& m1, const ShadeableIntersection& m2) {
+ return m1.materialId < m2.materialId;
+ }
+};
+
+struct not_zero {
+ __host__ __device__ bool operator()(const PathSegment& p) {
+ return (p.remainingBounces > 0);
+ }
+};
+
/**
* Wrapper for the __global__ call that sets up the kernel calls and does a ton
* of memory management
*/
-void pathtrace(uchar4 *pbo, int frame, int iter) {
- const int traceDepth = hst_scene->state.traceDepth;
- const Camera &cam = hst_scene->state.camera;
- const int pixelcount = cam.resolution.x * cam.resolution.y;
-
- // 2D block for generating ray from camera
- const dim3 blockSize2d(8, 8);
+void pathtrace(uchar4* pbo, int frame, int iter) {
+ auto start = std::chrono::high_resolution_clock::now();
+ const int traceDepth = hst_scene->state.traceDepth;
+ const Camera& cam = hst_scene->state.camera;
+ const int pixelcount = cam.resolution.x * cam.resolution.y;
+ const int pixelcount_sub = pixelcount * SUB_PIXEL_SAMPLE;
+
+ // 2D block for generating ray from camera
+ const dim3 blockSize2d(8, 8);
+ const dim3 blockSize3d(8, 8, SUB_PIXEL_SAMPLE);
const dim3 blocksPerGrid2d(
- (cam.resolution.x + blockSize2d.x - 1) / blockSize2d.x,
- (cam.resolution.y + blockSize2d.y - 1) / blockSize2d.y);
-
- // 1D block for path tracing
- const int blockSize1d = 128;
-
- ///////////////////////////////////////////////////////////////////////////
-
- // Recap:
- // * Initialize array of path rays (using rays that come out of the camera)
- // * You can pass the Camera object to that kernel.
- // * Each path ray must carry at minimum a (ray, color) pair,
- // * where color starts as the multiplicative identity, white = (1, 1, 1).
- // * This has already been done for you.
- // * For each depth:
- // * Compute an intersection in the scene for each path ray.
- // A very naive version of this has been implemented for you, but feel
- // free to add more primitives and/or a better algorithm.
- // Currently, intersection distance is recorded as a parametric distance,
- // t, or a "distance along the ray." t = -1.0 indicates no intersection.
- // * Color is attenuated (multiplied) by reflections off of any object
- // * TODO: Stream compact away all of the terminated paths.
- // You may use either your implementation or `thrust::remove_if` or its
- // cousins.
- // * Note that you can't really use a 2D kernel launch any more - switch
- // to 1D.
- // * TODO: Shade the rays that intersected something or didn't bottom out.
- // That is, color the ray by performing a color computation according
- // to the shader, then generate a new ray to continue the ray path.
- // We recommend just updating the ray's PathSegment in place.
- // Note that this step may come before or after stream compaction,
- // since some shaders you write may also cause a path to terminate.
- // * Finally, add this iteration's results to the image. This has been done
- // for you.
-
- // TODO: perform one iteration of path tracing
-
- generateRayFromCamera <<>>(cam, iter, traceDepth, dev_paths);
- checkCUDAError("generate camera ray");
-
- int depth = 0;
- PathSegment* dev_path_end = dev_paths + pixelcount;
- int num_paths = dev_path_end - dev_paths;
-
- // --- PathSegment Tracing Stage ---
- // Shoot ray into scene, bounce between objects, push shading chunks
-
- bool iterationComplete = false;
- while (!iterationComplete) {
-
- // clean shading chunks
- cudaMemset(dev_intersections, 0, pixelcount * sizeof(ShadeableIntersection));
-
- // tracing
- dim3 numblocksPathSegmentTracing = (num_paths + blockSize1d - 1) / blockSize1d;
- computeIntersections <<>> (
- depth
- , num_paths
- , dev_paths
- , dev_geoms
- , hst_scene->geoms.size()
- , dev_intersections
- );
- checkCUDAError("trace one bounce");
- cudaDeviceSynchronize();
- depth++;
-
-
- // TODO:
- // --- Shading Stage ---
- // Shade path segments based on intersections and generate new rays by
- // evaluating the BSDF.
- // Start off with just a big kernel that handles all the different
- // materials you have in the scenefile.
- // TODO: compare between directly shading the path segments and shading
- // path segments that have been reshuffled to be contiguous in memory.
-
- shadeFakeMaterial<<>> (
- iter,
- num_paths,
- dev_intersections,
- dev_paths,
- dev_materials
- );
- iterationComplete = true; // TODO: should be based off stream compaction results.
- }
+ (cam.resolution.x + blockSize3d.x - 1) / blockSize3d.x,
+ (cam.resolution.y + blockSize3d.y - 1) / blockSize3d.y);
+
+ // 1D block for path tracing
+ const int blockSize1d = 256;
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ // Recap:
+ // * Initialize array of path rays (using rays that come out of the camera)
+ // * You can pass the Camera object to that kernel.
+ // * Each path ray must carry at minimum a (ray, color) pair,
+ // * where color starts as the multiplicative identity, white = (1, 1, 1).
+ // * This has already been done for you.
+ // * For each depth:
+ // * Compute an intersection in the scene for each path ray.
+ // A very naive version of this has been implemented for you, but feel
+ // free to add more primitives and/or a better algorithm.
+ // Currently, intersection distance is recorded as a parametric distance,
+ // t, or a "distance along the ray." t = -1.0 indicates no intersection.
+ // * Color is attenuated (multiplied) by reflections off of any object
+ // * TODO: Stream compact away all of the terminated paths.
+ // You may use either your implementation or `thrust::remove_if` or its
+ // cousins.
+ // * Note that you can't really use a 2D kernel launch any more - switch
+ // to 1D.
+ // * TODO: Shade the rays that intersected something or didn't bottom out.
+ // That is, color the ray by performing a color computation according
+ // to the shader, then generate a new ray to continue the ray path.
+ // We recommend just updating the ray's PathSegment in place.
+ // Note that this step may come before or after stream compaction,
+ // since some shaders you write may also cause a path to terminate.
+ // * Finally, add this iteration's results to the image. This has been done
+ // for you.
+
+ // TODO: perform one iteration of path tracing
+
+ generateRayFromCamera << > > (cam, iter, traceDepth, dev_paths);
+ checkCUDAError("generate camera ray");
+
+ int depth = 0;
+ PathSegment* dev_path_end = dev_paths + pixelcount_sub;
+ int num_paths = dev_path_end - dev_paths;
+
+ // --- PathSegment Tracing Stage ---
+ // Shoot ray into scene, bounce between objects, push shading chunks
+
+ bool iterationComplete = false;
+ while (!iterationComplete) {
+
+ // clean shading chunks
+ cudaMemset(dev_intersections, 0, num_paths * sizeof(ShadeableIntersection));
+
+ // tracing
+ dim3 numblocksPathSegmentTracing = (num_paths + blockSize1d - 1) / blockSize1d;
+ bool use_cache = false; // because of anti-aliasing
+ if (depth == 0 && iter == 1 && use_cache) {
+ computeIntersections << > > (
+ depth
+ , num_paths
+ , dev_paths
+ , dev_geoms
+ , hst_scene->geoms.size()
+ , dev_intersections
+ );
+ checkCUDAError("trace one bounce");
+ cudaMemcpy(dev_intersections_cache, dev_intersections, pixelcount_sub * sizeof(ShadeableIntersection), cudaMemcpyDeviceToDevice);
+ }
+ else if (depth == 0 && use_cache){
+ cudaMemcpy(dev_intersections, dev_intersections_cache, pixelcount_sub * sizeof(ShadeableIntersection), cudaMemcpyDeviceToDevice);
+ }
+ else {
+ //printf("here");
+ computeIntersections << > > (
+ depth
+ , num_paths
+ , dev_paths
+ , dev_geoms
+ , hst_scene->geoms.size()
+ , dev_intersections
+ );
+ checkCUDAError("trace one bounce");
+ }
+ cudaDeviceSynchronize();
+ #if USE_MATERIAL_SORT
+ thrust::sort_by_key(thrust::device, dev_intersections, dev_intersections + num_paths, dev_paths, sort_material_id());
+ #endif
+
+ // TODO:
+ // --- Shading Stage ---
+ // Shade path segments based on intersections and generate new rays by
+ // evaluating the BSDF.
+ // Start off with just a big kernel that handles all the different
+ // materials you have in the scenefile.
+ // TODO: compare between directly shading the path segments and shading
+ // path segments that have been reshuffled to be contiguous in memory.
+
+ shadeMaterial << > > (
+ iter,
+ num_paths,
+ dev_intersections,
+ dev_paths,
+ dev_materials
+ );
+
+ PathSegment* newEnd = thrust::stable_partition(thrust::device, dev_paths, dev_paths + num_paths, not_zero());
+ num_paths = newEnd - dev_paths;
+ if (num_paths > 0) {
+ iterationComplete = false;
+ }
+ else {
+ iterationComplete = true;
+ }
+ depth++;
+ }
+
+ num_paths = dev_path_end - dev_paths;
- // Assemble this iteration and apply it to the image
- dim3 numBlocksPixels = (pixelcount + blockSize1d - 1) / blockSize1d;
- finalGather<<>>(num_paths, dev_image, dev_paths);
+ // Assemble this iteration and apply it to the image
+ dim3 numBlocksPixels = (pixelcount_sub + blockSize1d - 1) / blockSize1d;
+ finalGather << > > (num_paths, dev_image, dev_paths);
- ///////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////
- // Send results to OpenGL buffer for rendering
- sendImageToPBO<<>>(pbo, cam.resolution, iter, dev_image);
+ // Send results to OpenGL buffer for rendering
+ sendImageToPBO << > > (pbo, cam.resolution, iter, dev_image);
- // Retrieve image from GPU
- cudaMemcpy(hst_scene->state.image.data(), dev_image,
- pixelcount * sizeof(glm::vec3), cudaMemcpyDeviceToHost);
+ // Retrieve image from GPU
+ cudaMemcpy(hst_scene->state.image.data(), dev_image,
+ pixelcount * sizeof(glm::vec3), cudaMemcpyDeviceToHost);
+ std::chrono::duration diff = std::chrono::high_resolution_clock::now() - start;
+ std::cout << "Iteration time: " << diff.count() / (float)SUB_PIXEL_SAMPLE << std::endl;
- checkCUDAError("pathtrace");
+ checkCUDAError("pathtrace");
}
diff --git a/src/preview.cpp b/src/preview.cpp
index 4eb0bc13..1a17da9f 100644
--- a/src/preview.cpp
+++ b/src/preview.cpp
@@ -1,5 +1,6 @@
#define _CRT_SECURE_NO_DEPRECATE
#include
+
#include "main.h"
#include "preview.h"
@@ -171,7 +172,9 @@ bool init() {
void mainLoop() {
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
+
runCuda();
+
string title = "CIS565 Path Tracer | " + utilityCore::convertIntToString(iteration) + " Iterations";
glfwSetWindowTitle(window, title.c_str());
diff --git a/src/scene.cpp b/src/scene.cpp
index 3fb6239a..2511086c 100644
--- a/src/scene.cpp
+++ b/src/scene.cpp
@@ -3,6 +3,8 @@
#include
#include
#include
+#define TINYOBJLOADER_IMPLEMENTATION
+#include "tiny_obj_loader.h"
Scene::Scene(string filename) {
cout << "Reading scene from " << filename << " ..." << endl;
@@ -32,18 +34,56 @@ Scene::Scene(string filename) {
}
}
+int Scene::loadObj(string filename, std::vector& geom) {
+ tinyobj::attrib_t attrib;
+ std::vector shapes;
+ std::vector materials;
+ std::string warn;
+ std::string err;
+ bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, filename.c_str());
+ for (size_t shape_ind = 0; shape_ind < shapes.size(); shape_ind++) {
+ size_t index = 0;
+ for (size_t face_ind = 0; face_ind < shapes[shape_ind].mesh.num_face_vertices.size(); face_ind++) {
+ Geom new_geom;
+ new_geom.type = TRIANGLE;
+ for (size_t vertex_ind = 0; vertex_ind < 3; vertex_ind++) {
+ tinyobj::index_t ind = shapes[shape_ind].mesh.indices[(index)];
+ tinyobj::real_t vx = attrib.vertices[ind.vertex_index * 3 + 0];
+ tinyobj::real_t vy = attrib.vertices[ind.vertex_index * 3 + 1];
+ tinyobj::real_t vz = attrib.vertices[ind.vertex_index * 3 + 2];
+ tinyobj::real_t nx = 0;
+ tinyobj::real_t ny = 0;
+ tinyobj::real_t nz = 0;
+ if (attrib.normals.size() > 0) {
+ nx = attrib.normals[ind.vertex_index * 3 + 0];
+ ny = attrib.normals[ind.vertex_index * 3 + 1];
+ nz = attrib.normals[ind.vertex_index * 3 + 2];
+ }
+ new_geom.triangle.vertex[vertex_ind] = glm::vec3(vx, vy, vz);
+ new_geom.triangle.normals[vertex_ind] = glm::vec3(nx, ny, nz);
+ index++;
+ }
+ geom.push_back(new_geom);
+ }
+ }
+ return 1;
+}
+
int Scene::loadGeom(string objectid) {
int id = atoi(objectid.c_str());
if (id != geoms.size()) {
- cout << "ERROR: OBJECT ID does not match expected number of geoms" << endl;
- return -1;
- } else {
+ id = geoms.size();
+ //cout << "ERROR: OBJECT ID does not match expected number of geoms" << endl;
+ //return -1;
+ }
cout << "Loading Geom " << id << "..." << endl;
Geom newGeom;
+ std::vector mesh; // mesh loading
string line;
//load object type
utilityCore::safeGetline(fp_in, line);
+ vector parts = utilityCore::tokenizeString(line);
if (!line.empty() && fp_in.good()) {
if (strcmp(line.c_str(), "sphere") == 0) {
cout << "Creating new sphere..." << endl;
@@ -52,6 +92,11 @@ int Scene::loadGeom(string objectid) {
cout << "Creating new cube..." << endl;
newGeom.type = CUBE;
}
+ else if (strcmp(parts[0].c_str(), "mesh") == 0) {
+ cout << "Creating new mesh..." << endl;
+ newGeom.type = TRIANGLE;
+ loadObj(parts[1], mesh);
+ }
}
//link material
@@ -78,15 +123,35 @@ int Scene::loadGeom(string objectid) {
utilityCore::safeGetline(fp_in, line);
}
-
- newGeom.transform = utilityCore::buildTransformationMatrix(
+
+ if (mesh.size() > 0) {
+ for (size_t geom_ind = 0; geom_ind < mesh.size(); geom_ind++) {
+ Geom geom = mesh[geom_ind];
+ geom.type = TRIANGLE;
+ geom.materialid = newGeom.materialid;
+ geom.transform = utilityCore::buildTransformationMatrix(
+ newGeom.translation, newGeom.rotation, newGeom.scale);
+ geom.inverseTransform = glm::inverse(newGeom.transform);
+ geom.invTranspose = glm::inverseTranspose(newGeom.transform);
+ for (int ind = 0; ind < 3; ind++) {
+ geom.triangle.vertex[ind] = glm::vec3(geom.transform * glm::vec4(geom.triangle.vertex[ind], 1.0f));
+ geom.triangle.normals[ind] = glm::vec3(geom.invTranspose * glm::vec4(geom.triangle.normals[ind], 0.0f));
+ //printf("%f \n", geom.triangle.vertex[ind].y);
+ }
+ geoms.push_back(geom);
+ }
+ }
+ else {
+ newGeom.transform = utilityCore::buildTransformationMatrix(
newGeom.translation, newGeom.rotation, newGeom.scale);
- newGeom.inverseTransform = glm::inverse(newGeom.transform);
- newGeom.invTranspose = glm::inverseTranspose(newGeom.transform);
+ newGeom.inverseTransform = glm::inverse(newGeom.transform);
+ newGeom.invTranspose = glm::inverseTranspose(newGeom.transform);
- geoms.push_back(newGeom);
+ geoms.push_back(newGeom);
+ }
+
return 1;
- }
+
}
int Scene::loadCamera() {
@@ -112,6 +177,7 @@ int Scene::loadCamera() {
} else if (strcmp(tokens[0].c_str(), "FILE") == 0) {
state.imageName = tokens[1];
}
+
}
string line;
@@ -124,6 +190,10 @@ int Scene::loadCamera() {
camera.lookAt = glm::vec3(atof(tokens[1].c_str()), atof(tokens[2].c_str()), atof(tokens[3].c_str()));
} else if (strcmp(tokens[0].c_str(), "UP") == 0) {
camera.up = glm::vec3(atof(tokens[1].c_str()), atof(tokens[2].c_str()), atof(tokens[3].c_str()));
+ } else if (strcmp(tokens[0].c_str(), "APERTURE") == 0) {
+ camera.aperture = atof(tokens[1].c_str());
+ } else if (strcmp(tokens[0].c_str(), "FOCUS_DIST") == 0) {
+ camera.focus_dist = atof(tokens[1].c_str());
}
utilityCore::safeGetline(fp_in, line);
diff --git a/src/scene.h b/src/scene.h
index f29a9171..2404b9b5 100644
--- a/src/scene.h
+++ b/src/scene.h
@@ -16,6 +16,7 @@ class Scene {
int loadMaterial(string materialid);
int loadGeom(string objectid);
int loadCamera();
+ int Scene::loadObj(string filename, std::vector& geom);
public:
Scene(string filename);
~Scene();
diff --git a/src/sceneStructs.h b/src/sceneStructs.h
index da4dbf30..8b222341 100644
--- a/src/sceneStructs.h
+++ b/src/sceneStructs.h
@@ -10,6 +10,7 @@
enum GeomType {
SPHERE,
CUBE,
+ TRIANGLE,
};
struct Ray {
@@ -17,6 +18,11 @@ struct Ray {
glm::vec3 direction;
};
+struct Triangle {
+ glm::vec3 vertex[3];
+ glm::vec3 normals[3];
+};
+
struct Geom {
enum GeomType type;
int materialid;
@@ -26,6 +32,7 @@ struct Geom {
glm::mat4 transform;
glm::mat4 inverseTransform;
glm::mat4 invTranspose;
+ Triangle triangle;
};
struct Material {
@@ -49,6 +56,8 @@ struct Camera {
glm::vec3 right;
glm::vec2 fov;
glm::vec2 pixelLength;
+ float aperture = 0.0f;
+ float focus_dist = 1.0f;
};
struct RenderState {
@@ -72,5 +81,6 @@ struct PathSegment {
struct ShadeableIntersection {
float t;
glm::vec3 surfaceNormal;
+ glm::vec3 intersect_point;
int materialId;
};
diff --git a/src/tiny_obj_loader.cc b/src/tiny_obj_loader.cc
new file mode 100644
index 00000000..e57d0444
--- /dev/null
+++ b/src/tiny_obj_loader.cc
@@ -0,0 +1,2 @@
+#define TINYOBJLOADER_IMPLEMENTATION
+#include "tiny_obj_loader.h"
diff --git a/src/tiny_obj_loader.h b/src/tiny_obj_loader.h
new file mode 100644
index 00000000..38c8bd7c
--- /dev/null
+++ b/src/tiny_obj_loader.h
@@ -0,0 +1,3318 @@
+/*
+The MIT License (MIT)
+
+Copyright (c) 2012-Present, Syoyo Fujita and many contributors.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+//
+// version 2.0.0 : Add new object oriented API. 1.x API is still provided.
+// * Support line primitive.
+// * Support points primitive.
+// * Support multiple search path for .mtl(v1 API).
+// * Support vertex weight `vw`(as an tinyobj extension)
+// * Support escaped whitespece in mtllib
+// * Add robust triangulation using Mapbox earcut(TINYOBJLOADER_USE_MAPBOX_EARCUT).
+// version 1.4.0 : Modifed ParseTextureNameAndOption API
+// version 1.3.1 : Make ParseTextureNameAndOption API public
+// version 1.3.0 : Separate warning and error message(breaking API of LoadObj)
+// version 1.2.3 : Added color space extension('-colorspace') to tex opts.
+// version 1.2.2 : Parse multiple group names.
+// version 1.2.1 : Added initial support for line('l') primitive(PR #178)
+// version 1.2.0 : Hardened implementation(#175)
+// version 1.1.1 : Support smoothing groups(#162)
+// version 1.1.0 : Support parsing vertex color(#144)
+// version 1.0.8 : Fix parsing `g` tag just after `usemtl`(#138)
+// version 1.0.7 : Support multiple tex options(#126)
+// version 1.0.6 : Add TINYOBJLOADER_USE_DOUBLE option(#124)
+// version 1.0.5 : Ignore `Tr` when `d` exists in MTL(#43)
+// version 1.0.4 : Support multiple filenames for 'mtllib'(#112)
+// version 1.0.3 : Support parsing texture options(#85)
+// version 1.0.2 : Improve parsing speed by about a factor of 2 for large
+// files(#105)
+// version 1.0.1 : Fixes a shape is lost if obj ends with a 'usemtl'(#104)
+// version 1.0.0 : Change data structure. Change license from BSD to MIT.
+//
+
+//
+// Use this in *one* .cc
+// #define TINYOBJLOADER_IMPLEMENTATION
+// #include "tiny_obj_loader.h"
+//
+
+#ifndef TINY_OBJ_LOADER_H_
+#define TINY_OBJ_LOADER_H_
+
+#include