├── .gitignore
├── CMakeLists.txt
├── README.md
├── build
├── obj
│ ├── forme.obj
│ ├── light.obj
│ ├── plane.obj
│ ├── plane1.obj
│ ├── plane2.obj
│ ├── plane3.obj
│ ├── shape1.obj
│ └── triangle.obj
├── run.sh
└── scenes
│ ├── cbox1.sc
│ ├── cbox2.sc
│ ├── cbox3.sc
│ ├── forme_cbox-v2.sc
│ ├── forme_cbox.sc
│ ├── random1.sc
│ └── random2.sc
└── src
├── main.cpp
├── math
├── coremaths.h
├── mathshelpers.h
├── matrix3.cpp
├── matrix3.h
├── matrix4.cpp
├── matrix4.h
├── vec2.cpp
├── vec2.h
├── vec3.cpp
├── vec3.h
└── vec4.h
├── netpbm
├── image.h
├── netpbmloader.cpp
├── netpbmloader.h
├── pgmimage.cpp
├── pgmimage.h
├── ppmimage.cpp
└── ppmimage.h
└── pathtracer
├── bbox.cpp
├── bbox.h
├── camera.cpp
├── camera.h
├── color.h
├── config.h
├── helpers.h
├── intersection.h
├── material.h
├── object.h
├── objparser.cpp
├── objparser.h
├── pathtracer.h
├── plane.cpp
├── plane.h
├── ray.h
├── renderer.cpp
├── renderer.h
├── renderingtask.cpp
├── renderingtask.h
├── scene.cpp
├── scene.h
├── sceneparser.cpp
├── sceneparser.h
├── shading.cpp
├── shading.h
├── sphere.cpp
├── sphere.h
├── triangle.cpp
└── triangle.h
/.gitignore:
--------------------------------------------------------------------------------
1 | #cmake
2 | CmakeCache.txt
3 | Makefile
4 | CMakeFiles
5 | cmake_install.cmake
6 |
7 | #compiled source
8 | *.o
9 | *.out
10 | *.a
11 |
12 | #latex
13 | *.aux
14 | *.synctex.gz
15 |
16 | #other files
17 | *.swp
18 | *.swo
19 | *.log
20 |
21 | build/images/*
22 | build/linux/
23 | build/osx/
24 |
25 | #os file
26 | .DS_Store
27 | .DS_Store?
28 | ._*
29 | .Spotlight-V100
30 | .Trashes
31 | ehthumbs.db
32 | Thumbs.db
33 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8)
2 | project(pathtracer)
3 |
4 | if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
5 | set(CMAKE_CXX_FLAGS "-g -std=c++11 -stdlib=libc++ -Wall -g -O0 -fms-extensions")
6 | endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
7 |
8 | if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
9 | set(CMAKE_CXX_FLAGS "-g -std=c++0x -pthread -Wall -g -O0 -fms-extensions")
10 | endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
11 |
12 | file(GLOB_RECURSE SOURCES "src/*.cpp")
13 | file(GLOB_RECURSE HEADERS "src/*.h")
14 |
15 | set(INCLUDE_DIRS "")
16 | foreach(_headerFile ${HEADERS})
17 | get_filename_component(_dir ${_headerFile} PATH)
18 | list(APPEND INCLUDE_DIRS ${_dir})
19 | endforeach()
20 | list(REMOVE_DUPLICATES INCLUDE_DIRS)
21 |
22 | include_directories(${INCLUDE_DIRS})
23 |
24 | add_executable(pathtracer.out ${SOURCES})
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | pathtracer
2 | ==========
3 |
4 | version 0.9.2
5 |
6 | dependencies
7 | ------------
8 |
9 | This project uses cmake.
10 |
11 | #### mac osx
12 |
13 | Download and install [CMake](http://www.cmake.org/cmake/resources/software.html)
14 | if you don't already have it.
15 | To simplify installation you may use [Homebrew](http://brew.sh):
16 |
17 | ```bash
18 | brew install cmake
19 | ```
20 |
21 | #### linux (ubuntu)
22 |
23 | ```bash
24 | sudo apt-get install cmake
25 | ```
26 |
27 | build and run
28 | -------------
29 |
30 | To build and run it you can either do:
31 |
32 | ```bash
33 | $ cd build
34 | $ ./run.sh scene_file_name samples_per_pixel
35 | ```
36 |
37 | which will give you more information about the time it took to render the image, and save a png image into a images/ subfolder with the standard name scene-hour-sppx.png, or:
38 |
39 | ```bash
40 | $ cd build
41 | $ cmake .. && make
42 | $ ./pathtracer.out scenes/scene_file_name samples_per_pixel
43 | ```
44 | which will only output an image.ppm file.
45 |
46 | usage
47 | -----
48 |
49 | #### scenes
50 |
51 | To define a camera, you can provide a lens size (for depth of field) and the focus plane distance, if you don't, the rendering will be without depth of field (pinhole camera). For the other parameters, **p** is the position, **la** is the _look at_ position, and **res** defines the resolution of the film of the camera:
52 |
53 | ```
54 | camera lens(0.08) focus(1.0) p(0.0, 2.5, -4.0) la(0.0, 2.5, 0.0) res(640, 480)
55 | ```
56 |
57 | To define basic objects (planes & spheres), the object can be either a sphere with **s** or a plane with **p**, next **p** is the position of this object, **e** is its emission, **c** is its color, the material can be **s**, **d** or **r** for respectively _specular_, _diffuse_ or _refractive_ material.
58 |
59 | ```
60 | object:s|p p(2.0, 1.0, 0.0) e(0.0, 0.0, 0.0) c(1.0, 1.0, 1.0) material:s|d|r
61 | ```
62 |
63 | For meshes, you first have to define its _.obj_ file location, and the last parameters are the same as basic objects.
64 |
65 | ```
66 | mesh:obj/plane1.obj p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(1.0, 1.0, 1.0) material:s|d|r
67 | ```
68 |
69 | #### example
70 |
71 | ```bash
72 | # cornell box scene
73 | camera lens(0.08) focus(1.0) p(0.0, 2.5, -4.0) la(0.0, 2.5, 0.0) res(640, 480)
74 |
75 | # light sphere
76 | object:s p(1.0, 3.5, 3.5) e(2.5, 2.5, 2.5) c(1.0, 1.0, 1.0) material:d
77 |
78 | # spheres
79 | object:s p(2.0, 1.0, 0.0) e(0.0, 0.0, 0.0) c(1.0, 1.0, 1.0) material:s
80 | object:s p(-2.9, 1.0, 2.0) e(0.0, 0.0, 0.0) c(1.0, 1.0, 1.0) material:r
81 |
82 | # floor plane
83 | object:p p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(0.88, 0.85, 0.78) material:d
84 |
85 | # meshes / walls
86 | mesh:obj/plane1.obj p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(1.0, 1.0, 1.0) material:d
87 | mesh:obj/plane2.obj p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(0.41, 0.21, 0.35) material:d
88 | mesh:obj/plane3.obj p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(0.81, 0.29, 0.0) material:d
89 | ```
90 |
91 | #### results
92 |
93 | 
94 |
95 | First attempts on depth of field (there's still some artifacts):
96 |
97 | 
98 |
99 | licence
100 | =======
101 |
102 | Copyright (C) 2014 Naaji Karim (karim.naaji@gmail.com)
103 |
104 | This program is free software: you can redistribute it and/or modify
105 | it under the terms of the GNU General Public License as published by
106 | the Free Software Foundation, either version 3 of the License, or
107 | (at your option) any later version.
108 |
109 | This program is distributed in the hope that it will be useful,
110 | but WITHOUT ANY WARRANTY; without even the implied warranty of
111 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
112 | GNU General Public License for more details.
113 |
114 | You should have received a copy of the GNU General Public License
115 | along with this program. If not, see .
116 |
--------------------------------------------------------------------------------
/build/obj/forme.obj:
--------------------------------------------------------------------------------
1 | # Blender v2.62 (sub 0) OBJ File: ''
2 | # www.blender.org
3 | o Cube
4 | v 1.621475 0.751957 -2.058985
5 | v 0.058860 2.465518 1.654575
6 | v -3.594482 1.096932 3.170309
7 | v -1.941140 2.465518 -0.345425
8 | v 0.058860 4.465518 -0.345424
9 | v 0.794039 5.200698 2.389756
10 | v -1.941141 4.465518 1.654575
11 | v -1.941140 4.465518 -0.345425
12 | vn -0.032991 -0.998911 0.032991
13 | vn -0.132030 0.982413 -0.132030
14 | vn 0.991462 0.092203 0.092203
15 | vn 0.091146 0.091146 0.991657
16 | vn -0.946877 0.227402 -0.227403
17 | vn -0.223436 0.223437 -0.948764
18 | s off
19 | f 1//1 2//1 3//1
20 | f 1//1 3//1 4//1
21 | f 5//2 8//2 7//2
22 | f 5//2 7//2 6//2
23 | f 1//3 5//3 6//3
24 | f 1//3 6//3 2//3
25 | f 2//4 6//4 7//4
26 | f 2//4 7//4 3//4
27 | f 3//5 7//5 8//5
28 | f 3//5 8//5 4//5
29 | f 5//6 1//6 4//6
30 | f 5//6 4//6 8//6
31 |
--------------------------------------------------------------------------------
/build/obj/light.obj:
--------------------------------------------------------------------------------
1 | v 4.1 4.8 4.5
2 | v 4.5 4.8 4.1
3 | v 4.6 4.0 4.2
4 | v 4.2 4.0 4.6
5 |
6 | f 1//2 2//3 3//1
7 | f 3//1 1//4 4//3
8 |
--------------------------------------------------------------------------------
/build/obj/plane.obj:
--------------------------------------------------------------------------------
1 | v -50.0 50.0 3.0
2 | v 50.0 50.0 3.0
3 | v 50.0 0.0 3.0
4 | v -50.0 0.0 3.0
5 |
6 | f 1//2 2//3 3//1
7 | f 1//3 3//4 4//1
8 |
--------------------------------------------------------------------------------
/build/obj/plane1.obj:
--------------------------------------------------------------------------------
1 | v -5.0 5.0 5.0
2 | v 5.0 5.0 5.0
3 | v 5.0 0.0 5.0
4 | v -5.0 0.0 5.0
5 | v -5.0 5.0 -5.0
6 | v 5.0 5.0 -5.0
7 | v 5.0 0.0 -5.0
8 | v -5.0 0.0 -5.0
9 |
10 | f 1//2 2//3 3//4
11 | f 1//3 3//4 4//1
12 | f 1//2 2//6 6//1
13 | f 1//5 5//6 6//1
14 | f 5//6 6//7 7//5
15 | f 5//7 7//8 8//5
16 |
--------------------------------------------------------------------------------
/build/obj/plane2.obj:
--------------------------------------------------------------------------------
1 | v -5.0 5.0 -5.0
2 | v -5.0 5.0 5.0
3 | v -5.0 0.0 -5.0
4 | v -5.0 0.0 5.0
5 | f 1//2 2//3 3//1
6 | f 3//2 2//4 4//3
7 |
--------------------------------------------------------------------------------
/build/obj/plane3.obj:
--------------------------------------------------------------------------------
1 | v 5.0 5.0 -5.0
2 | v 5.0 5.0 5.0
3 | v 5.0 0.0 -5.0
4 | v 5.0 0.0 5.0
5 | f 1//2 2//3 3//1
6 | f 3//2 2//4 4//3
7 |
--------------------------------------------------------------------------------
/build/obj/shape1.obj:
--------------------------------------------------------------------------------
1 | # Blender v2.66 (sub 1) OBJ File: ''
2 | # www.blender.org
3 | v -5.000000 4.999999 5.000000
4 | v 5.000000 4.999999 5.000000
5 | v 5.000000 -0.000001 5.000000
6 | v -5.000000 -0.000001 5.000000
7 | v 5.000000 5.000001 -4.999999
8 | v -5.000000 5.000001 -4.999999
9 | v 5.000000 0.000001 -4.999999
10 | v -5.000000 0.000001 -4.999999
11 | v 0.696011 -0.186876 0.503495
12 | v 0.696011 -0.186876 2.503495
13 | v -1.303990 -0.186876 2.503494
14 | v -1.303989 -0.186876 0.503494
15 | v 0.696011 1.813124 0.503495
16 | v 0.696010 1.813124 2.503495
17 | v -1.303990 1.813124 2.503494
18 | v -1.303989 1.813124 0.503495
19 | v -0.212886 2.999198 2.566036
20 | v -0.212886 2.999198 1.145405
21 | v 1.207746 2.999198 1.145405
22 | v 1.207746 2.999198 2.566036
23 | v -0.212886 1.578567 2.566036
24 | v -0.212885 1.578567 1.145404
25 | v 1.207746 1.578567 1.145405
26 | v 1.207746 1.578567 2.566036
27 | v 1.948406 0.043726 0.762700
28 | v 1.948406 0.043726 2.136357
29 | v 0.574748 0.043726 2.136357
30 | v 0.574749 0.043726 0.762699
31 | v 1.948406 1.417384 0.762700
32 | v 1.948405 1.417384 2.136357
33 | v 0.574748 1.417383 2.136357
34 | v 0.574748 1.417383 0.762700
35 | v -0.670174 1.529619 0.062029
36 | v -0.670174 1.529619 1.374141
37 | v -1.982286 1.529618 1.374140
38 | v -1.982286 1.529618 0.062028
39 | v -0.670174 2.841731 0.062029
40 | v -0.670175 2.841731 1.374141
41 | v -1.982286 2.841730 1.374140
42 | v -1.982286 2.841730 0.062028
43 | v -1.266461 3.619861 1.415171
44 | v -1.266461 3.619861 0.483157
45 | v -0.334447 3.619861 0.483158
46 | v -0.334447 3.619861 1.415172
47 | v -1.266461 2.687848 1.415171
48 | v -1.266460 2.687848 0.483157
49 | v -0.334447 2.687848 0.483158
50 | v -0.334447 2.687848 1.415171
51 | v 0.151467 1.680907 0.232082
52 | v 0.151467 1.680907 1.133278
53 | v -0.749729 1.680906 1.133278
54 | v -0.749729 1.680906 0.232082
55 | v 0.151467 2.582103 0.232083
56 | v 0.151467 2.582103 1.133278
57 | v -0.749729 2.582102 1.133278
58 | v -0.749729 2.582102 0.232082
59 | f 1//1 2//1 3//1
60 | f 1//1 3//1 4//1
61 | f 1//2 2//2 5//2
62 | f 1//3 6//3 5//3
63 | f 6//1 5//1 7//1
64 | f 6//1 7//1 8//1
65 | f 17//3 18//3 19//3
66 | f 21//2 24//2 23//2
67 | f 17//4 21//4 22//4
68 | f 18//5 22//5 19//5
69 | f 19//6 23//6 20//6
70 | f 21//1 17//1 20//1
71 | f 20//3 17//3 19//3
72 | f 22//2 21//2 23//2
73 | f 18//7 17//7 22//7
74 | f 22//8 23//8 19//8
75 | f 23//6 24//6 20//6
76 | f 24//1 21//1 20//1
77 | f 9//3 10//3 11//3
78 | f 13//2 16//2 14//2
79 | f 9//4 13//4 14//4
80 | f 10//5 14//5 11//5
81 | f 11//6 15//6 12//6
82 | f 13//1 9//1 12//1
83 | f 12//3 9//3 11//3
84 | f 16//2 15//2 14//2
85 | f 10//7 9//7 14//7
86 | f 14//5 15//5 11//5
87 | f 15//6 16//6 12//6
88 | f 16//1 13//1 12//1
89 | f 25//3 26//3 27//3
90 | f 29//2 32//2 30//2
91 | f 25//4 29//4 30//4
92 | f 26//5 30//5 27//5
93 | f 27//6 31//6 28//6
94 | f 29//1 25//1 28//1
95 | f 28//3 25//3 27//3
96 | f 32//2 31//2 30//2
97 | f 26//7 25//7 30//7
98 | f 30//5 31//5 27//5
99 | f 31//6 32//6 28//6
100 | f 32//1 29//1 28//1
101 | f 41//3 42//3 43//3
102 | f 45//2 48//2 46//2
103 | f 41//4 45//4 46//4
104 | f 42//8 46//8 43//8
105 | f 43//6 47//6 44//6
106 | f 45//9 41//9 44//9
107 | f 44//3 41//3 43//3
108 | f 48//2 47//2 46//2
109 | f 42//7 41//7 46//7
110 | f 46//8 47//8 43//8
111 | f 47//6 48//6 44//6
112 | f 48//9 45//9 44//9
113 | f 33//3 34//3 35//3
114 | f 37//10 40//10 38//10
115 | f 33//4 37//4 38//4
116 | f 34//8 38//8 35//8
117 | f 35//6 39//6 36//6
118 | f 37//9 33//9 40//9
119 | f 36//3 33//3 35//3
120 | f 40//10 39//10 38//10
121 | f 34//7 33//7 38//7
122 | f 38//8 39//8 35//8
123 | f 39//6 40//6 36//6
124 | f 33//9 36//9 40//9
125 | f 49//11 50//11 51//11
126 | f 53//10 56//10 54//10
127 | f 49//4 53//4 54//4
128 | f 50//8 54//8 51//8
129 | f 51//6 55//6 52//6
130 | f 53//9 49//9 56//9
131 | f 52//11 49//11 51//11
132 | f 56//10 55//10 54//10
133 | f 50//7 49//7 54//7
134 | f 54//8 55//8 51//8
135 | f 55//6 56//6 52//6
136 | f 49//9 52//9 56//9
137 |
--------------------------------------------------------------------------------
/build/obj/triangle.obj:
--------------------------------------------------------------------------------
1 | v -1.0 0.0 0.3
2 | v 0.0 1.0 0.4
3 | v 1.0 0.0 -0.4
4 | f 1//2 2//3 3//1
5 |
--------------------------------------------------------------------------------
/build/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # ./run.sh scene_name samples_per_pixel
3 | # compile, build and run the path tracer
4 | # stores the output inside images/
5 |
6 | cmake .. && make
7 |
8 | if [[ $? == 0 ]]
9 | then
10 | d1=$(date +"%s")
11 |
12 | ./pathtracer.out scenes/$1 $2
13 |
14 | if [[ $? != 0 ]]
15 | then
16 | echo -e "$(tput setaf 1)Bash: An error occured while running ./pathtracer"
17 | exit $?
18 | fi
19 |
20 | d2=$(date +"%s")
21 | d=$(($d2-$d1))
22 |
23 | echo -e "$(tput bold)Bash: $(($d/60)) minutes and $(($d%60)) seconds elapsed."
24 |
25 | now=`date +"%d%b%Y-%s"`
26 | scene=`echo $1 | cut -d'.' -f1`
27 | filename="images/$scene-$now-$2sppx.png"
28 |
29 | mkdir -p images
30 | convert image.ppm $filename
31 |
32 | echo -e "$(tput bold)Bash: Image saved as $filename"
33 | if [[ "$OSTYPE" == "linux-gnu" ]]; then
34 | xdg-open $filename
35 | elif [[ "$OSTYPE" == "darwin12" ]]; then
36 | open $filename
37 | fi
38 |
39 | echo -e "$(tput bold)Bash: Remove of output file image.ppm"
40 | rm image.ppm
41 | fi
42 |
--------------------------------------------------------------------------------
/build/scenes/cbox1.sc:
--------------------------------------------------------------------------------
1 | version 0.9.2
2 | # test scene
3 | camera lens(0.08) focus(1.5) p(0.0, 2.5, -4.0) la(0.0, 2.5, 0.0) res(640, 480)
4 |
5 | # spheres
6 | object:s p(2.5, 1.0, 2.5) e(0.0, 0.0, 0.0) c(0.85, 1.0, 0.9) material:d
7 | object:s p(-2.0, 1.0, 0.5) e(0.0, 0.0, 0.0) c(0.5, 0.5, 0.5) material:s
8 | object:s p(0.0, 4.5, 0.0) e(5.0, 5.0, 5.0) c(1.0, 1.0, 1.0) material:s
9 |
10 | # floor plane
11 | object:p p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(0.88, 0.85, 0.78) material:d
12 |
13 | # meshes
14 | mesh:obj/plane1.obj p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(1.0, 1.0, 1.0) material:d
15 | mesh:obj/plane2.obj p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(0.41, 0.21, 0.35) material:d
16 | mesh:obj/plane3.obj p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(0.81, 0.29, 0.0) material:d
17 |
--------------------------------------------------------------------------------
/build/scenes/cbox2.sc:
--------------------------------------------------------------------------------
1 | version 0.9.2
2 | # test scene
3 | camera lens(0.1) focus(2.0) p(-1.0, 1.5, -4.0) la(0.0, 1.0, 0.0) res(640, 480)
4 |
5 | # spheres
6 | object:s p(0.0, 2.5, 3.5) e(3.5, 3.5, 3.5) c(1.0, 1.0, 1.0) material:d
7 | object:s p(0.0, 1.0, -1.0) e(0.0, 0.0, 0.0) c(1.0, 1.0, 1.0) material:r
8 |
9 | # floor plane
10 | object:p p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(0.88, 0.88, 0.88) material:d
11 |
12 | # meshes
13 | mesh:obj/plane1.obj p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(1.0, 1.0, 1.0) material:d
14 | mesh:obj/plane2.obj p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(0.15, 0.28, 0.41) material:d
15 | mesh:obj/plane3.obj p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(0.96, 0.72, 0.01) material:d
16 |
--------------------------------------------------------------------------------
/build/scenes/cbox3.sc:
--------------------------------------------------------------------------------
1 | version 0.9.2
2 | # test scene
3 | camera lens(0.1) focus(2.3) p(1.0, 2.5, -1.8) la(0.5, 1.5, 0.0) res(640, 480)
4 |
5 | # spheres
6 | object:s p(3.0, 2.5, 4.0) e(3.5, 3.5, 3.5) c(1.0, 1.0, 1.0) material:d
7 | #object:s p(1.0, 1.0, -2.0) e(0.0, 0.0, 0.0) c(0.3, 0.3, 0.3) material:s
8 | #object:s p(-1.7, 1.0, -2.0) e(0.0, 0.0, 0.0) c(1.0, 1.0, 1.0) material:s
9 |
10 | # floor plane
11 | object:p p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(0.88, 0.85, 0.78) material:d
12 |
13 | # meshes
14 | mesh:obj/shape1.obj p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(1.0, 1.0, 1.0) material:d
15 | mesh:obj/plane2.obj p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(0.15, 0.28, 0.41) material:d
16 | mesh:obj/plane3.obj p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(0.96, 0.72, 0.01) material:d
17 |
--------------------------------------------------------------------------------
/build/scenes/forme_cbox-v2.sc:
--------------------------------------------------------------------------------
1 | version 0.9.2
2 | # test scene
3 | camera lens(0.001) focus(2.0) p(0.0, 4.5, -4.0) la(0.0, 0.2, 0.0) res(640, 480)
4 |
5 | # spheres
6 | object:s p(1.0, 1.5, 3.5) e(2.6, 2.6, 2.6) c(1.0, 1.0, 1.0) material:d
7 | object:s p(2.0, 1.0, 0.0) e(0.0, 0.0, 0.0) c(1.0, 1.0, 1.0) material:s
8 | object:s p(0.0, 2.5, 0.0) e(0.0, 0.0, 0.0) c(1.0, 1.0, 1.0) material:r
9 | object:s p(-2.0, 1.5, 3.5) e(0.0, 0.0, 0.0) c(1.0, 1.0, 1.0) material:r
10 | object:s p(-1.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(1.0, 1.0, 1.0) material:d
11 |
12 | # floor plane
13 | object:p p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(0.88, 0.85, 0.78) material:d
14 |
15 | # meshes
16 | #mesh:obj/plane1.obj p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(1.0, 1.0, 1.0) material:d
17 | mesh:obj/plane2.obj p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(0.15, 0.28, 0.41) material:d
18 | mesh:obj/plane3.obj p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(0.96, 0.72, 0.01) material:d
--------------------------------------------------------------------------------
/build/scenes/forme_cbox.sc:
--------------------------------------------------------------------------------
1 | versio 0.9.2
2 | # test scene
3 | camera lens(0.0) focus(0.0) p(0.0, 2.5, -4.0) la(0.0, 2.5, 0.0) res(640, 480)
4 |
5 | # spheres
6 | #object:s p(2.5, 1.0, 2.5) e(0.0, 0.0, 0.0) c(0.85, 1.0, 0.9) material:d
7 | #object:s p(-2.0, 1.0, 0.5) e(0.0, 0.0, 0.0) c(0.5, 0.5, 0.5) material:s
8 |
9 | # old light hidden by forme.obj:
10 | # object:s p(1.0, 2.5, 3.5) e(6.0, 6.0, 6.0) c(1.0, 1.0, 1.0) material:d
11 |
12 | object:s p(1.0, 3.5, 3.5) e(2.5, 2.5, 2.5) c(1.0, 1.0, 1.0) material:d
13 | object:s p(-1.0, 1.5, 0.0) e(0.0, 0.0, 0.0) c(0.25, 0.25, 0.25) material:s
14 | object:s p(2.0, 1.0, 0.0) e(0.0, 0.0, 0.0) c(1.0, 1.0, 1.0) material:s
15 | object:s p(0.0, 3.5, 0.0) e(0.0, 0.0, 0.0) c(0.95, 0.67, 0.68) material:r
16 | object:s p(-2.9, 1.0, 2.0) e(0.0, 0.0, 0.0) c(1.0, 1.0, 1.0) material:r
17 | #mesh:obj/forme.obj p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(1.0, 1.0, 1.0) material:d
18 |
19 | # floor plane
20 | object:p p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(0.88, 0.85, 0.78) material:d
21 |
22 | # meshes
23 | mesh:obj/plane1.obj p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(1.0, 1.0, 1.0) material:d
24 | mesh:obj/plane2.obj p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(0.41, 0.21, 0.35) material:d
25 | mesh:obj/plane3.obj p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(0.81, 0.29, 0.0) material:d
26 |
--------------------------------------------------------------------------------
/build/scenes/random1.sc:
--------------------------------------------------------------------------------
1 | version 0.9.2
2 | # test scene
3 | camera lens(0.0) focus(0.0) p(0.0, 2.5, -5.0) la(0.0, 0.0, -1.0) res(640, 480)
4 | # spheres
5 | object:s p(0.0, 3.0, 4.0) e(1.0, 1.0, 1.0) c(1.0, 1.0, 1.0) material:d
6 | object:s p(0.0, 5.0, -10.0) e(100.0, 100.0, 100.0) c(1.0, 1.0, 1.0) material:d
7 | object:s p(0.0, -0.5, -2.0) e(1.0, 1.0, 0.5) c(1.0, 1.0, 1.0) material:d
8 | object:s p(2.0, 2.0, -1.0) e(0.0, 0.0, 0.0) c(1.0, 1.0, 1.0) material:d
9 | #object:s p(0.0, 1.5, 0.5) e( 0.0, 0.0, 0.0) c(0.5, 0.5, 0.5) material:s
10 | object:s p(-2.5, 1.0, 0.0) e( 0.0, 0.0, 0.0) c(0.8, 0.6, 0.5) material:s
11 | # plane
12 | object:p p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(0.9, 0.85, 0.8) material:d
13 |
14 |
--------------------------------------------------------------------------------
/build/scenes/random2.sc:
--------------------------------------------------------------------------------
1 | version 0.9.2
2 | # test scene
3 | camera lens(0.05) focus(1.0) p(0.0, 2.5, -2.5) la(0.0, 0.0, 0.0) res(640, 480)
4 |
5 | # spheres
6 | object:s p(0.0, 1.0, 0.0) e(4.0, 4.0, 4.0) c(1.0, 1.0, 1.0) material:d
7 |
8 | # floor plane
9 | object:p p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(0.88, 0.85, 0.78) material:d
10 |
11 | # meshes
12 | #mesh:obj/plane1.obj p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(1.0, 1.0, 1.0) material:d
13 | #mesh:obj/plane2.obj p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(1.0, 0.71, 0.21) material:d
14 | #mesh:obj/plane3.obj p(0.0, 0.0, 0.0) e(0.0, 0.0, 0.0) c(0.0, 0.29, 0.61) material:d
15 |
--------------------------------------------------------------------------------
/src/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "config.h"
4 | #include "renderer.h"
5 | #include "sceneparser.h"
6 | #include "scene.h"
7 | #include "pathtracer.h"
8 |
9 | int main(int argc, char** argv) {
10 | if(argc < 3) {
11 | cerr << "Abort: Must specify scene file and sppxl" << endl;
12 | return -1;
13 | }
14 |
15 | string scenefile(argv[1]);
16 |
17 | PrintVersion();
18 |
19 | SceneParser parser(scenefile);
20 | Scene *scene = parser.BuildScene();
21 |
22 | PPMImage *film = scene->GetCamera()->Film();
23 |
24 | Renderer renderer(atoi(argv[2]));
25 | renderer.Init(*film);
26 |
27 | renderer.Render(scene);
28 |
29 | NetPBMLoader loader;
30 | loader.SavePPM(*film, "image");
31 |
32 | delete scene;
33 |
34 | return 0;
35 | }
36 |
--------------------------------------------------------------------------------
/src/math/coremaths.h:
--------------------------------------------------------------------------------
1 | #ifndef __CORE_MATHS_H__
2 | #define __CORE_MATHS_H__
3 |
4 | #include
5 |
6 | #include "matrix4.h"
7 | #include "matrix3.h"
8 |
9 | #include "vec2.h"
10 | #include "vec3.h"
11 | #include "vec4.h"
12 |
13 | #include "mathshelpers.h"
14 |
15 | #endif
16 |
--------------------------------------------------------------------------------
/src/math/mathshelpers.h:
--------------------------------------------------------------------------------
1 | #ifndef __MATHS_HELPERS_H__
2 | #define __MATHS_HELPERS_H__
3 |
4 | #ifdef M_PI
5 | #undef M_PI
6 | #endif
7 | #define M_PI 3.14159265358979323846f
8 | #define INV_PI 0.31830988618379067154f
9 | #define INV_TWOPI 0.15915494309189533577f
10 | #define INV_FOURPI 0.07957747154594766788f
11 |
12 | #define PI_360 (M_PI * 2.0)
13 |
14 | #ifndef INFINITY
15 | #define INFINITY FLT_MAX
16 | #endif
17 |
18 | #define EPSILON 1e-5f
19 |
20 | inline float Radians(float deg) {
21 | return ((float)M_PI/180.f) * deg;
22 | }
23 |
24 | inline float Degrees(float rad) {
25 | return (180.f/(float)M_PI) * rad;
26 | }
27 |
28 | inline float Lerp(float t, float v1, float v2) {
29 | return (1.f - t) * v1 + t * v2;
30 | }
31 |
32 | inline float Clamp(float val, float low, float high) {
33 | if(val > high) return high;
34 | else if(val < low) return low;
35 | else return val;
36 | }
37 |
38 | inline float Max(float a, float b) {
39 | return a > b ? a : b;
40 | }
41 |
42 | inline float Min(float a, float b) {
43 | return a > b ? b : a;
44 | }
45 |
46 | inline void Swap(float& a, float& b) {
47 | float tmp = a;
48 | a = b;
49 | b = tmp;
50 | }
51 |
52 | #endif
53 |
--------------------------------------------------------------------------------
/src/math/matrix3.cpp:
--------------------------------------------------------------------------------
1 | #include "matrix3.h"
2 |
3 | Matrix3::Matrix3()
4 | {
5 | ToIdentity();
6 | }
7 |
8 | Matrix3::Matrix3(float elements[9]) {
9 | memcpy(this->array, elements, 9 * sizeof(float));
10 | }
11 |
12 | Matrix3 Matrix3::GetInverse(const Matrix4& m1)
13 | {
14 | float a11 = m1.array[10] * m1.array[5] - m1.array[6] * m1.array[9];
15 | float a21 = - m1.array[10] * m1.array[1] + m1.array[2] * m1.array[9];
16 | float a31 = m1.array[6] * m1.array[1] - m1.array[2] * m1.array[5];
17 | float a12 = - m1.array[10] * m1.array[4] + m1.array[6] * m1.array[8];
18 | float a22 = m1.array[10] * m1.array[0] - m1.array[2] * m1.array[8];
19 | float a32 = - m1.array[6] * m1.array[0] + m1.array[2] * m1.array[4];
20 | float a13 = m1.array[9] * m1.array[4] - m1.array[5] * m1.array[8];
21 | float a23 = - m1.array[9] * m1.array[0] + m1.array[1] * m1.array[8];
22 | float a33 = m1.array[5] * m1.array[0] - m1.array[1] * m1.array[4];
23 |
24 | float det = m1.array[0] * a11 + m1.array[1] * a12 + m1.array[2] * a13;
25 |
26 | if (det == 0.0)
27 | {
28 | return Matrix3::Identity();
29 | }
30 |
31 | Matrix3 m2;
32 |
33 | float idet = 1.0 / det;
34 |
35 | m2.array[0] = idet * a11; m2.array[1] = idet * a21; m2.array[2] = idet * a31;
36 | m2.array[3] = idet * a12; m2.array[4] = idet * a22; m2.array[5] = idet * a32;
37 | m2.array[6] = idet * a13; m2.array[7] = idet * a23; m2.array[8] = idet * a33;
38 |
39 | return m2;
40 | }
41 |
42 | void Matrix3::Transpose()
43 | {
44 | float tmp;
45 |
46 | tmp = array[1]; array[1] = array[3]; array[3] = tmp;
47 | tmp = array[2]; array[2] = array[6]; array[6] = tmp;
48 | tmp = array[5]; array[5] = array[7]; array[7] = tmp;
49 | }
50 |
51 | Matrix3 Matrix3::Identity()
52 | {
53 | Matrix3 m;
54 | m.ToIdentity();
55 | return m;
56 | }
57 |
58 | void Matrix3::ToZero() {
59 | for(int i = 0; i < 9; i++) {
60 | array[i] = 0.0f;
61 | }
62 | }
63 |
64 | void Matrix3::ToIdentity()
65 | {
66 | ToZero();
67 | array[0] = array[4] = array[8] = 1;
68 | }
--------------------------------------------------------------------------------
/src/math/matrix3.h:
--------------------------------------------------------------------------------
1 | #ifndef __MATRIX3_H__
2 | #define __MATRIX3_H__
3 |
4 | #include "matrix4.h"
5 |
6 | class Matrix3 {
7 | public:
8 | union
9 | {
10 | float data[3][3];
11 | float array[9];
12 | };
13 |
14 | Matrix3();
15 | Matrix3(float elements[9]);
16 |
17 | void Transpose();
18 | void ToIdentity();
19 | void ToZero();
20 |
21 | static Matrix3 Identity();
22 | static Matrix3 GetInverse(const Matrix4& m);
23 | };
24 |
25 | #endif
--------------------------------------------------------------------------------
/src/math/matrix4.cpp:
--------------------------------------------------------------------------------
1 | #include "matrix4.h"
2 |
3 | Matrix4::Matrix4(void) {
4 | ToIdentity();
5 | }
6 |
7 | Matrix4::Matrix4(float elements[16]) {
8 | memcpy(this->array, elements, 16 * sizeof(float));
9 | }
10 |
11 | Matrix4::~Matrix4(void) {
12 | ToIdentity();
13 | }
14 |
15 | void Matrix4::ToIdentity() {
16 | ToZero();
17 |
18 | array[0] = 1.0f;
19 | array[5] = 1.0f;
20 | array[10] = 1.0f;
21 | array[15] = 1.0f;
22 | }
23 |
24 | Matrix4& Matrix4::operator=(const Matrix4 &a) {
25 | if(this != &a) {
26 | for(int i = 0; i < 16; i++) {
27 | array[i] = a.array[i];
28 | }
29 | }
30 |
31 | return *this;
32 | }
33 |
34 |
35 | void Matrix4::ToZero() {
36 | for(int i = 0; i < 16; i++) {
37 | array[i] = 0.0f;
38 | }
39 | }
40 |
41 | Vec3 Matrix4::GetPositionVector() const {
42 | return Vec3(array[12], array[13], array[14]);
43 | }
44 |
45 | void Matrix4::SetPositionVector(const Vec3 in) {
46 | array[12] = in.x;
47 | array[13] = in.y;
48 | array[14] = in.z;
49 | }
50 |
51 | Vec3 Matrix4::GetScalingVector() const{
52 | return Vec3(array[0], array[5], array[10]);
53 | }
54 |
55 | void Matrix4::SetScalingVector(const Vec3 &in) {
56 | array[0] = in.x;
57 | array[5] = in.y;
58 | array[10] = in.z;
59 | }
60 |
61 | Matrix4 Matrix4::Identity() {
62 | Matrix4 m;
63 |
64 | m.ToIdentity();
65 | return m;
66 | }
67 |
68 | Matrix4 Matrix4::CreatePerspective(float znear, float zfar, float aspect, float fov) {
69 | Matrix4 m;
70 |
71 | const float h = 1.0f / tan(fov * PI_360);
72 | float neg_depth = znear-zfar;
73 |
74 | m.array[0] = h / aspect;
75 | m.array[5] = h;
76 | m.array[10] = (zfar+znear) / neg_depth;
77 | m.array[11] = -1.0f;
78 | m.array[14] = 2.0f * (znear*zfar) / neg_depth;
79 | m.array[15] = 0.0f;
80 |
81 | return m;
82 | }
83 |
84 | Matrix4 Matrix4::CreateOrthographic(float znear, float zfar,float right, float left, float top, float bottom) {
85 | Matrix4 m;
86 |
87 | m.array[0] = 2.0f / (right-left);
88 | m.array[5] = 2.0f / (top-bottom);
89 | m.array[10] = -2.0f / (zfar-znear);
90 |
91 | m.array[12] = -(right+left) / (right-left);
92 | m.array[13] = -(top+bottom) / (top-bottom);
93 | m.array[14] = -(zfar+znear) / (zfar-znear);
94 | m.array[15] = 1.0f;
95 |
96 | return m;
97 | }
98 |
99 | Matrix4 Matrix4::CreateLookAt(const Vec3 &from, const Vec3 &lookingAt) {
100 | Matrix4 r;
101 | Matrix4 m;
102 | Vec3 f = (lookingAt - from);
103 | Vec3 up = Vec3::Up();
104 |
105 | r.SetPositionVector(Vec3(-from.x, -from.y, -from.z));
106 | f.Normalize();
107 |
108 | Vec3 s = f.Cross(up);
109 | Vec3 u = s.Cross(f);
110 |
111 | m.array[0] = s.x;
112 | m.array[4] = s.y;
113 | m.array[8] = s.z;
114 |
115 | m.array[1] = u.x;
116 | m.array[5] = u.y;
117 | m.array[9] = u.z;
118 |
119 | m.array[2] = -f.x;
120 | m.array[6] = -f.y;
121 | m.array[10] = -f.z;
122 |
123 | return m*r;
124 | }
125 |
126 | Matrix4 Matrix4::CreateRotation(float degrees, const Vec3 &inaxis) {
127 | Matrix4 m;
128 |
129 | Vec3 axis = inaxis;
130 |
131 | axis.Normalize();
132 |
133 | float c = cos((float)Radians(degrees));
134 | float s = sin((float)Radians(degrees));
135 |
136 | m.array[0] = (axis.x * axis.x) * (1.0f - c) + c;
137 | m.array[1] = (axis.y * axis.x) * (1.0f - c) + (axis.z * s);
138 | m.array[2] = (axis.z * axis.x) * (1.0f - c) - (axis.y * s);
139 |
140 | m.array[4] = (axis.x * axis.y) * (1.0f - c) - (axis.z * s);
141 | m.array[5] = (axis.y * axis.y) * (1.0f - c) + c;
142 | m.array[6] = (axis.z * axis.y) * (1.0f - c) + (axis.x * s);
143 |
144 | m.array[8] = (axis.x * axis.z) * (1.0f - c) + (axis.y * s);
145 | m.array[9] = (axis.y * axis.z) * (1.0f - c) - (axis.x * s);
146 | m.array[10] = (axis.z * axis.z) * (1.0f - c) + c;
147 |
148 | return m;
149 | }
150 |
151 | Matrix4 Matrix4::CreateScale(const Vec3 &scale) {
152 | Matrix4 m;
153 |
154 | m.array[0] = scale.x;
155 | m.array[5] = scale.y;
156 | m.array[10] = scale.z;
157 |
158 | return m;
159 | }
160 |
161 | Matrix4 Matrix4::CreateTranslation(const Vec3 &translation) {
162 | Matrix4 m;
163 |
164 | m.array[12] = translation.x;
165 | m.array[13] = translation.y;
166 | m.array[14] = translation.z;
167 |
168 | return m;
169 | }
--------------------------------------------------------------------------------
/src/math/matrix4.h:
--------------------------------------------------------------------------------
1 | #ifndef __MATRIX4_H__
2 | #define __MATRIX4_H__
3 |
4 | #include
5 | #include
6 | #include "vec3.h"
7 | #include "vec4.h"
8 | #include "mathshelpers.h"
9 |
10 | class Matrix4 {
11 | public:
12 | union
13 | {
14 | float data[4][4];
15 | float array[16];
16 | };
17 |
18 | Matrix4(void);
19 | Matrix4(float elements[16]);
20 | ~Matrix4(void);
21 | Matrix4& operator=(const Matrix4 &a);
22 |
23 | void ToZero();
24 | void ToIdentity();
25 | Vec3 GetPositionVector() const;
26 | void SetPositionVector(const Vec3 in);
27 | Vec3 GetScalingVector() const;
28 | void SetScalingVector(const Vec3 &in);
29 |
30 | static Matrix4 CreateRotation(float degrees, const Vec3 &axis);
31 | static Matrix4 CreateScale(const Vec3 &scale);
32 | static Matrix4 CreateTranslation(const Vec3 &translation);
33 | static Matrix4 CreatePerspective(float znear, float zfar, float aspect, float fov);
34 | static Matrix4 CreateOrthographic(float znear, float zfar,float right, float left, float top, float bottom);
35 | static Matrix4 CreateLookAt(const Vec3 &from, const Vec3 &lookingAt);
36 |
37 | static Matrix4 Identity();
38 |
39 | inline Matrix4 operator*(const Matrix4 &a) const {
40 | Matrix4 out;
41 |
42 | for(unsigned int r = 0; r < 4; ++r) {
43 | for(unsigned int c = 0; c < 4; ++c) {
44 | out.array[c + (r*4)] = 0.0f;
45 | for(unsigned int i = 0; i < 4; ++i) {
46 | out.array[c + (r*4)] += this->array[c+(i*4)] * a.array[(r*4)+i];
47 | }
48 | }
49 | }
50 |
51 | return out;
52 | }
53 |
54 | inline Vec3 operator*(const Vec3 &v) const {
55 | Vec3 vec;
56 |
57 | float temp;
58 |
59 | vec.x = v.x * array[0] + v.y * array[4] + v.z * array[8] + array[12];
60 | vec.y = v.x * array[1] + v.y * array[5] + v.z * array[9] + array[13];
61 | vec.z = v.x * array[2] + v.y * array[6] + v.z * array[10] + array[14];
62 |
63 | temp = v.x * array[3] + v.y * array[7] + v.z * array[11] + array[15];
64 |
65 | vec.x = vec.x / temp;
66 | vec.y = vec.y / temp;
67 | vec.z = vec.z / temp;
68 |
69 | return vec;
70 | };
71 |
72 | inline Vec4 operator*(const Vec4 &v) const {
73 | return Vec4(
74 | v.x*array[0] + v.y * array[4] + v.z * array[8] + v.w * array[12],
75 | v.x*array[1] + v.y * array[5] + v.z * array[9] + v.w * array[13],
76 | v.x*array[2] + v.y * array[6] + v.z * array[10] + v.w * array[14],
77 | v.x*array[3] + v.y * array[7] + v.z * array[11] + v.w * array[15]
78 | );
79 | };
80 |
81 | inline friend std::ostream& operator<<(std::ostream& o, const Matrix4& m) {
82 | o << "\t" << m.array[0] << " " << m.array[1] << " " << m.array[2] << " " << m.array [3] << std::endl;
83 | o << "\t" << m.array[4] << " " << m.array[5] << " " << m.array[6] << " " << m.array [7] << std::endl;
84 | o << "\t" << m.array[8] << " " << m.array[9] << " " << m.array[10] << " " << m.array [11] << std::endl;
85 | o << "\t" << m.array[12] << " " << m.array[13] << " " << m.array[14] << " " << m.array [15] << std::endl;
86 | return o;
87 | }
88 | };
89 |
90 | #endif
91 |
--------------------------------------------------------------------------------
/src/math/vec2.cpp:
--------------------------------------------------------------------------------
1 | #include "vec2.h"
2 |
3 | Vec2::Vec2() {
4 | x = 0;
5 | y = 0;
6 | }
7 |
8 | Vec2::Vec2(float x_, float y_) {
9 | x = x_;
10 | y = y_;
11 | }
12 |
13 | Vec2::Vec2(const Vec2& v) {
14 | x = v.x;
15 | y = v.y;
16 | }
17 |
18 | Vec2::Vec2(const Vec2& from,const Vec2& to) {
19 | x = to.x - from.x;
20 | y = to.y - from.y;
21 | }
22 |
23 | Vec2& Vec2::operator= (const Vec2& v) {
24 | x = v.x;
25 | y = v.y;
26 | return *this;
27 | }
28 |
29 | Vec2& Vec2::operator+= (const Vec2& v) {
30 | x += v.x;
31 | y += v.y;
32 | return *this;
33 | }
34 |
35 | Vec2 Vec2::operator+ (const Vec2& v) const {
36 | Vec2 t = *this;
37 | t += v;
38 | return t;
39 | }
40 |
41 | Vec2 Vec2::operator+(const float a) const {
42 | Vec2 t = *this;
43 | t.x += a;
44 | t.y += a;
45 | return t;
46 | }
47 |
48 | Vec2 Vec2::operator-(const float a) const {
49 | Vec2 t = *this;
50 | t.x -= a;
51 | t.y -= a;
52 | return t;
53 | }
54 |
55 | Vec2 & Vec2::operator-= (const Vec2& v) {
56 | x -= v.x;
57 | y -= v.y;
58 | return *this;
59 | }
60 |
61 | Vec2 Vec2::operator-(const Vec2& v) const {
62 | Vec2 t = *this;
63 | t -= v;
64 | return t;
65 | }
66 |
67 | Vec2 & Vec2::operator*=(const float a) {
68 | x *= a;
69 | y *= a;
70 | return *this;
71 | }
72 |
73 | Vec2 Vec2::operator*(const float a)const {
74 | Vec2 t = *this;
75 | t *= a;
76 | return t;
77 | }
78 |
79 | Vec2 operator*(const float a, const Vec2 & v) {
80 | return Vec2(v.x*a, v.y*a);
81 | }
82 |
83 | Vec2& Vec2::operator/=(const float a) {
84 | x /= a;
85 | y /= a;
86 | return *this;
87 | }
88 |
89 | Vec2 Vec2::operator/(const float a)const {
90 | Vec2 t = *this;
91 | t /= a;
92 | return t;
93 | }
94 |
95 | float Vec2::length() const {
96 | return sqrt(x*x+y*y);
97 | }
98 |
99 | Vec2& Vec2::normalize() {
100 | (*this) /= length();
101 | return (*this);
102 | }
103 |
104 | float Vec2::operator[](const int dim) const {
105 | if(dim == 0) return x;
106 | else return y;
107 | }
108 |
--------------------------------------------------------------------------------
/src/math/vec2.h:
--------------------------------------------------------------------------------
1 | #ifndef __VEC2_H__
2 | #define __VEC2_H__
3 |
4 | #include
5 | #include
6 |
7 | using std::ostream;
8 |
9 | class Vec2 {
10 | public:
11 | union {
12 | struct { float x, y; };
13 | float v[2];
14 | };
15 |
16 | Vec2();
17 | Vec2(float x, float y);
18 | Vec2(const Vec2& v);
19 | Vec2(const Vec2& from,const Vec2 & to);
20 |
21 | Vec2& operator=(const Vec2 & v);
22 | Vec2& operator+=(const Vec2 & v);
23 | Vec2 operator+(const float a) const;
24 | Vec2 operator-(const float a) const;
25 | Vec2 operator+(const Vec2 & v) const;
26 | Vec2& operator-=(const Vec2 & v);
27 | Vec2 operator-(const Vec2 & v) const;
28 | Vec2& operator*=(const float a);
29 | Vec2 operator*(const float a)const;
30 | Vec2& operator/=(const float a);
31 | Vec2 operator/(const float a)const;
32 | float operator[](const int dim) const;
33 | friend Vec2 operator*(const float a,const Vec2 & v);
34 |
35 | float length()const;
36 | Vec2& normalize();
37 |
38 |
39 | inline friend ostream& operator<<(ostream& o, const Vec2& vec) {
40 | o << "(" << vec.x << ", " << vec.y << ")";
41 | return o;
42 | }
43 | };
44 | #endif
45 |
--------------------------------------------------------------------------------
/src/math/vec3.cpp:
--------------------------------------------------------------------------------
1 | #include "vec3.h"
2 |
3 | Vec3::Vec3() {
4 | x = 0;
5 | y = 0;
6 | z = 0;
7 | }
8 |
9 | Vec3::Vec3(float x_,float y_,float z_) {
10 | x = x_;
11 | y = y_;
12 | z = z_;
13 | }
14 |
15 | Vec3::Vec3(float val) {
16 | x = val;
17 | y = val;
18 | z = val;
19 | }
20 |
21 | Vec3::Vec3(const Vec3& v) {
22 | x = v.x;
23 | y = v.y;
24 | z = v.z;
25 | }
26 |
27 | Vec3::Vec3(const Vec3& from,const Vec3& to) {
28 | x = to.x - from.x;
29 | y = to.y - from.y;
30 | z = to.z - from.z;
31 | }
32 |
33 | Vec3& Vec3::operator=(const Vec3& v) {
34 | x = v.x;
35 | y = v.y;
36 | z = v.z;
37 | return *this;
38 | }
39 |
40 | Vec3& Vec3::operator+=(const Vec3& v) {
41 | x += v.x;
42 | y += v.y;
43 | z += v.z;
44 | return *this;
45 | }
46 |
47 | Vec3 Vec3::operator+(const Vec3& v) const {
48 | Vec3 t = *this;
49 | t += v;
50 | return t;
51 | }
52 |
53 | Vec3& Vec3::operator-=(const Vec3& v) {
54 | x -= v.x;
55 | y -= v.y;
56 | z -= v.z;
57 | return *this;
58 | }
59 |
60 | Vec3 Vec3::operator-(const Vec3& v) const {
61 | Vec3 t = *this;
62 | t -= v;
63 | return t;
64 | }
65 |
66 | Vec3 Vec3::operator-() const {
67 | Vec3 t = *this * -1.0f;
68 | return t;
69 | }
70 |
71 | Vec3& Vec3::operator*=(const float a) {
72 | x *= a;
73 | y *= a;
74 | z *= a;
75 | return *this;
76 | }
77 |
78 | Vec3 Vec3::operator*(const float a) const {
79 | Vec3 t = *this;
80 | t *= a;
81 | return t;
82 | }
83 |
84 | Vec3 operator*(const float a ,const Vec3& v) {
85 | return Vec3(v.x*a,v.y*a,v.z*a);
86 | }
87 |
88 | Vec3 Vec3::operator*(const Vec3& v) const {
89 | return Vec3(x*v.x, y*v.y, z*v.z);
90 | }
91 |
92 | Vec3& Vec3::operator/=(const float a) {
93 | x /= a;
94 | y /= a;
95 | z /= a;
96 | return *this;
97 | }
98 |
99 | Vec3 Vec3::operator/(const float a) const {
100 | Vec3 t = *this;
101 | t /= a;
102 | return t;
103 | }
104 |
105 | float Vec3::operator[](const int dim) const {
106 | if(dim == 0) return x;
107 | else if(dim == 1) return y;
108 | else return z;
109 | }
110 |
111 | Vec3 Vec3::Cross(const Vec3& v) const {
112 | Vec3 t;
113 | t.x = y*v.z - z*v.y;
114 | t.y = z*v.x - x*v.z;
115 | t.z = x*v.y - y*v.x;
116 | return t;
117 | }
118 |
119 | Vec3 Vec3::Abs(Vec3 v) {
120 | v.x = fabs(v.x);
121 | v.y = fabs(v.y);
122 | v.z = fabs(v.z);
123 | return v;
124 | }
125 |
126 | Vec3 Vec3::VClamp(Vec3 v, float low, float high) {
127 | v.x = Clamp(v.x, low, high);
128 | v.y = Clamp(v.y, low, high);
129 | v.z = Clamp(v.z, low, high);
130 | return v;
131 | }
132 |
133 | float Vec3::Dot(const Vec3& v) const {
134 | return x*v.x + y*v.y + z*v.z;
135 | }
136 |
137 | Vec3 Vec3::Up() {
138 | return Vec3(0.0, 1.0, 0.0);
139 | }
140 |
141 | float Vec3::Length() const {
142 | return sqrt(x*x + y*y + z*z);
143 | }
144 |
145 | Vec3& Vec3::Normalize() {
146 | (*this) /= Length();
147 | return (*this);
148 | }
149 |
150 | Vec3 Vec3::Zero() {
151 | return Vec3(0, 0, 0);
152 | }
153 |
--------------------------------------------------------------------------------
/src/math/vec3.h:
--------------------------------------------------------------------------------
1 | #ifndef __VEC3_H__
2 | #define __VEC3_H__
3 |
4 | #include
5 | #include
6 | #include "mathshelpers.h"
7 |
8 | using std::ostream;
9 |
10 | class Vec3 {
11 | public:
12 | union {
13 | struct { float x, y, z; };
14 | struct { float r, g, b; };
15 | float v[3];
16 | };
17 |
18 | Vec3();
19 | Vec3(float x,float y,float z);
20 | Vec3(float val);
21 | Vec3(const Vec3& v);
22 | Vec3(const Vec3& from,const Vec3& to);
23 |
24 | Vec3& operator=(const Vec3& v);
25 | Vec3& operator+=(const Vec3& v);
26 | Vec3 operator+(const Vec3& v) const;
27 | Vec3& operator-=(const Vec3& v);
28 | Vec3 operator-(const Vec3& v) const;
29 | Vec3 operator-() const;
30 | Vec3& operator*=(const float a);
31 | Vec3 operator*(const float a)const;
32 | Vec3 operator*(const Vec3& v) const;
33 | Vec3& operator/=(const float a);
34 | Vec3 operator/(const float a)const;
35 | float operator[](const int dim) const;
36 | friend Vec3 operator*(const float a, const Vec3& v);
37 |
38 | static Vec3 Zero();
39 | static Vec3 VClamp(Vec3 v, float low, float high);
40 | static Vec3 Abs(Vec3 v);
41 | static Vec3 Up();
42 | Vec3 Cross(const Vec3& v) const;
43 | float Length() const;
44 | float Dot(const Vec3& v) const;
45 | Vec3& Normalize();
46 |
47 | inline friend ostream& operator<<(ostream& o, const Vec3& vec) {
48 | o << "(" << vec.x << ", " << vec.y << ", " << vec.z << ")";
49 | return o;
50 | }
51 | };
52 |
53 | #endif
54 |
--------------------------------------------------------------------------------
/src/math/vec4.h:
--------------------------------------------------------------------------------
1 | #ifndef __VECTOR4_H__
2 | #define __VECTOR4_H__
3 |
4 | class Vec4 {
5 | public:
6 | union {
7 | struct { float x, y, z, w; };
8 | struct { float r, g, b, a; };
9 | float v[4];
10 | };
11 |
12 | Vec4(void) {
13 | x = y = z = w = 1.0f;
14 | }
15 |
16 | Vec4(float x, float y, float z, float w) {
17 | this->x = x;
18 | this->y = y;
19 | this->z = z;
20 | this->w = w;
21 | }
22 |
23 |
24 | float operator[](const int dim) const {
25 | if(dim == 0) return x;
26 | else if(dim == 1) return y;
27 | else if(dim == 2) return z;
28 | else return w;
29 | }
30 | };
31 |
32 | #endif
33 |
--------------------------------------------------------------------------------
/src/netpbm/image.h:
--------------------------------------------------------------------------------
1 | #ifndef __IMAGE_H__
2 | #define __IMAGE_H__
3 |
4 | template class Image {
5 | public:
6 | Image() {}
7 | Image(int width, int height) {
8 | this->width = width;
9 | this->height = height;
10 | }
11 |
12 | virtual ~Image() {}
13 |
14 | int GetWidth() const { return width; }
15 | int GetHeight() const { return height; }
16 | int GetSize() const { return width * height; }
17 |
18 | virtual T operator()(int i, int j) const = 0;
19 | virtual T& operator()(int i, int j) = 0;
20 |
21 | protected:
22 | int width;
23 | int height;
24 | };
25 |
26 | #endif
27 |
--------------------------------------------------------------------------------
/src/netpbm/netpbmloader.cpp:
--------------------------------------------------------------------------------
1 | #include "netpbmloader.h"
2 |
3 | void NetPBMLoader::Read(std::string filename, std::string ext, s_NetPBMFileDesc* fileDesc) {
4 | std::string path = filename + ext;
5 | std::string line1;
6 | std::string line2;
7 | std::ifstream file(path.c_str(), std::ios::in | std::ios::binary);
8 | std::ifstream::pos_type start, end, size;
9 | std::ifstream::off_type newStart;
10 |
11 | if(!file) {
12 | std::cerr << "Error while opening " << path << std::endl;
13 | throw std::runtime_error("Can't open file" + path);
14 | }
15 |
16 | std::cout << "Reading " << path << std::endl;
17 |
18 | getline(file, line1);
19 | start = file.tellg();
20 | getline(file, line2);
21 |
22 | std::cout << "Header: " << std::endl;
23 | std::cout << line1 << std::endl;
24 |
25 | if(line2[0] != '#') {
26 | file.seekg(start, std::ios::beg);
27 | } else {
28 | std::cout << line2 << std::endl;
29 | }
30 |
31 | file >> fileDesc->length;
32 | file >> fileDesc->width;
33 | file >> fileDesc->colors;
34 |
35 | std::cout << " - Width: " << fileDesc->width << ", Length: " << fileDesc->length << std::endl;
36 | std::cout << " - Colors: " << fileDesc->colors << std::endl;
37 |
38 | start = file.tellg();
39 | file.seekg (0, std::ios::end);
40 | end = file.tellg();
41 | size = end - start;
42 |
43 | char* memblock = new char[size];
44 | newStart = static_cast(start);
45 | file.seekg(newStart+1, std::ios::beg);
46 | file.read(memblock, size);
47 | file.close();
48 |
49 | fileDesc->memblock = (unsigned char*)memblock;
50 | }
51 |
52 | PGMImage NetPBMLoader::LoadPGM(std::string filename) {
53 | s_NetPBMFileDesc* fileDesc = new s_NetPBMFileDesc();
54 | Read(filename, ".pgm", fileDesc);
55 | PGMImage image(fileDesc->length, fileDesc->width);
56 |
57 | for(int i = 0; i < image.GetWidth(); ++i) {
58 | for(int j = 0; j < image.GetHeight(); ++j) {
59 | image(i, j) = (float)(fileDesc->memblock[i*image.GetWidth()+j]);
60 | }
61 | }
62 |
63 | delete[] fileDesc->memblock;
64 | delete fileDesc;
65 |
66 | return image;
67 | }
68 |
69 | PPMImage NetPBMLoader::LoadPPM(std::string filename) {
70 | s_NetPBMFileDesc* fileDesc = new s_NetPBMFileDesc();
71 | Read(filename, ".ppm", fileDesc);
72 | PPMImage image(fileDesc->length, fileDesc->width);
73 | const int nbChannels = 3;
74 |
75 | for(int i = 0; i < image.GetWidth(); ++i) {
76 | for(int j = 0; j < image.GetHeight()*nbChannels; j+=3) {
77 | Vec3 color;
78 | color.r = (float)(fileDesc->memblock[i*image.GetWidth()*nbChannels+j]);
79 | color.g = (float)(fileDesc->memblock[i*image.GetWidth()*nbChannels+j+1]);
80 | color.b = (float)(fileDesc->memblock[i*image.GetWidth()*nbChannels+j+2]);
81 | image(i, j/nbChannels) = color;
82 | }
83 | }
84 |
85 | delete[] fileDesc->memblock;
86 | delete fileDesc;
87 |
88 | return image;
89 | }
90 |
91 |
92 | void NetPBMLoader::SavePGM(PGMImage& pgmimage, std::string filename) {
93 | std::string path = filename + ".pgm";
94 | std::ofstream file(path.c_str(), std::ios::out | std::ios::binary);
95 |
96 | if(file.is_open()) {
97 | time_t now = time(0);
98 | char* dt = ctime(&now);
99 |
100 | file << "P5\n";
101 | file << "# " << dt;
102 | file << pgmimage.GetWidth() << " " << pgmimage.GetHeight() << "\n";
103 | file << COLOR_LEVELS << "\n";
104 |
105 | for(int j = 0; j < pgmimage.GetHeight(); ++j) {
106 | for(int i = 0; i < pgmimage.GetWidth(); ++i) {
107 | file << (char)(pgmimage(i, j));
108 | }
109 | }
110 |
111 | file.close();
112 | std::cout << "Saved file " << path << std::endl;
113 | }
114 | }
115 |
116 | void NetPBMLoader::SavePPM(PPMImage& pgmimage, std::string filename) {
117 | std::string path = filename + ".ppm";
118 | std::ofstream file(path.c_str(), std::ios::out | std::ios::binary);
119 |
120 | if(file.is_open()) {
121 | time_t now = time(0);
122 | char* dt = ctime(&now);
123 |
124 | file << "P6\n";
125 | file << "# " << dt;
126 | file << pgmimage.GetWidth() << " " << pgmimage.GetHeight() << "\n";
127 | file << COLOR_LEVELS << "\n";
128 |
129 | for(int j = 0; j < pgmimage.GetHeight(); ++j) {
130 | for(int i = 0; i < pgmimage.GetWidth(); ++i) {
131 | file << (char)(pgmimage(i, j).r);
132 | file << (char)(pgmimage(i, j).g);
133 | file << (char)(pgmimage(i, j).b);
134 | }
135 | }
136 |
137 | file.close();
138 | std::cout << "Saved file " << path << std::endl;
139 | }
140 | }
141 |
142 |
--------------------------------------------------------------------------------
/src/netpbm/netpbmloader.h:
--------------------------------------------------------------------------------
1 | #ifndef __NET_PBM_LOADER_H__
2 | #define __NET_PBM_LOADER_H__
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #include "vec3.h"
12 | #include "pgmimage.h"
13 | #include "ppmimage.h"
14 |
15 | #define COLOR_LEVELS 255
16 |
17 | struct s_NetPBMFileDesc {
18 | unsigned int length;
19 | unsigned int width;
20 | unsigned int colors;
21 | unsigned char* memblock;
22 | };
23 |
24 | class NetPBMLoader {
25 | public:
26 | NetPBMLoader() {};
27 | ~NetPBMLoader() {};
28 | PGMImage LoadPGM(std::string filename);
29 | PPMImage LoadPPM(std::string filename);
30 | void SavePGM(PGMImage& pgmimage, std::string filename);
31 | void SavePPM(PPMImage& ppmimage, std::string filename);
32 |
33 | private:
34 | void Read(std::string filename, std::string ext, s_NetPBMFileDesc* fileDesc);
35 | };
36 |
37 | #endif
38 |
--------------------------------------------------------------------------------
/src/netpbm/pgmimage.cpp:
--------------------------------------------------------------------------------
1 | #include "pgmimage.h"
2 |
3 | PGMImage::PGMImage() : Image(0, 0) {
4 | data = NULL;
5 | }
6 |
7 | PGMImage::PGMImage(int width_, int height_) : Image(width_, height_) {
8 | data = new float[height*width];
9 |
10 | for(int i = 0; i < width; ++i) {
11 | for(int j = 0; j < height; ++j) {
12 | (*this)(i,j) = 0.0;
13 | }
14 | }
15 | }
16 |
17 | PGMImage::PGMImage(const PGMImage& image) {
18 | height = image.height;
19 | width = image.width;
20 | data = new float[height*width];
21 |
22 | for(int i = 0; i < width; ++i) {
23 | for(int j = 0; j < height; ++j) {
24 | (*this)(i,j) = image(i,j);
25 | }
26 | }
27 | }
28 |
29 | PGMImage& PGMImage::operator=(const PGMImage& image) {
30 | if(this != &image) {
31 | if(data != NULL) {
32 | delete[] data;
33 | }
34 | height = image.height;
35 | width = image.width;
36 |
37 | data = new float[height*width];
38 | for(int i = 0; i < width; ++i) {
39 | for(int j = 0; j < height; ++j) {
40 | (*this)(i,j) = image(i,j);
41 | }
42 | }
43 | }
44 | return *this;
45 | }
46 |
47 | PGMImage::~PGMImage() {
48 | if(data != NULL) {
49 | delete[] data;
50 | }
51 | }
52 |
53 | float PGMImage::operator()(int i, int j) const {
54 | return data[j*height+i];
55 | }
56 |
57 | float& PGMImage::operator()(int i, int j) {
58 | return data[j*height+i];
59 | }
60 |
61 | void PGMImage::Threshold(float threshold, float newValue) {
62 | for(int i = 0; i < width; ++i) {
63 | for(int j = 0; j < height; ++j) {
64 | if((*this)(i,j) > threshold) {
65 | (*this)(i,j) = newValue;
66 | }
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/netpbm/pgmimage.h:
--------------------------------------------------------------------------------
1 | #ifndef __PGM_IMAGE_H__
2 | #define __PGM_IMAGE_H__
3 |
4 | #include
5 | #include "image.h"
6 |
7 | class PGMImage : public Image {
8 | public:
9 | PGMImage();
10 | PGMImage(int width, int height);
11 | PGMImage(const PGMImage& image);
12 | PGMImage& operator=(const PGMImage& image);
13 | ~PGMImage();
14 |
15 | float operator()(int i, int j) const;
16 | float& operator()(int i, int j);
17 |
18 | void Threshold(float threshold, float newValue);
19 | private:
20 | float* data;
21 | };
22 |
23 | #endif
24 |
--------------------------------------------------------------------------------
/src/netpbm/ppmimage.cpp:
--------------------------------------------------------------------------------
1 | #include "ppmimage.h"
2 |
3 | PPMImage::PPMImage() : Image(0, 0) {
4 | data = NULL;
5 | }
6 |
7 | PPMImage::PPMImage(int width_, int height_) : Image(width_, height_) {
8 | data = new Vec3*[height];
9 | for(int j = 0; j < height; ++j) {
10 | data[j] = new Vec3[width];
11 | }
12 |
13 | for(int i = 0; i < width; ++i) {
14 | for(int j = 0; j < height; ++j) {
15 | (*this)(i,j) = Vec3::Zero();
16 | }
17 | }
18 | }
19 |
20 | PPMImage::PPMImage(const PPMImage& image) {
21 | height = image.height;
22 | width = image.width;
23 | data = new Vec3*[height];
24 | for(int j = 0; j < height; ++j) {
25 | data[j] = new Vec3[width];
26 | }
27 |
28 | for(int i = 0; i < width; ++i) {
29 | for(int j = 0; j < height; ++j) {
30 | (*this)(i,j) = image(i,j);
31 | }
32 | }
33 | }
34 |
35 | PPMImage& PPMImage::operator=(const PPMImage& image) {
36 | if(this != &image) {
37 | if(data != NULL) {
38 | for(int j = 0; j < height; ++j)
39 | delete[] data[j];
40 | delete[] data;
41 | }
42 | height = image.height;
43 | width = image.width;
44 |
45 | data = new Vec3*[height];
46 | for(int i = 0; i < width; ++i) {
47 | data[i] = new Vec3[width];
48 | }
49 | for(int i = 0; i < width; ++i) {
50 | for(int j = 0; j < height; ++j) {
51 | (*this)(i,j) = image(i,j);
52 | }
53 | }
54 | }
55 | return *this;
56 | }
57 |
58 | PPMImage::~PPMImage() {
59 | if(data != NULL) {
60 | for(int j = 0; j < height; ++j)
61 | delete[] data[j];
62 | delete[] data;
63 | }
64 | }
65 |
66 | Vec3 PPMImage::operator()(int i, int j) const {
67 | return data[j][i];
68 | }
69 |
70 | Vec3& PPMImage::operator()(int i, int j) {
71 | return data[j][i];
72 | }
73 |
74 | float* PPMImage::Data() const {
75 | return reinterpret_cast(data);
76 | }
77 |
--------------------------------------------------------------------------------
/src/netpbm/ppmimage.h:
--------------------------------------------------------------------------------
1 | #ifndef __PPM_IMAGE_H__
2 | #define __PPM_IMAGE_H__
3 |
4 | #include
5 | #include
6 |
7 | #include "vec3.h"
8 | #include "image.h"
9 |
10 | class PPMImage : public Image {
11 | public:
12 | PPMImage();
13 | PPMImage(int width, int height);
14 | PPMImage(const PPMImage& image);
15 | PPMImage& operator=(const PPMImage& image);
16 | ~PPMImage();
17 |
18 | Vec3 operator()(int i, int j) const;
19 | Vec3& operator()(int i, int j);
20 | int GetGrayscale() const;
21 | float* Data() const;
22 | private:
23 | int grayscale;
24 | Vec3** data;
25 | };
26 |
27 | #endif
28 |
--------------------------------------------------------------------------------
/src/pathtracer/bbox.cpp:
--------------------------------------------------------------------------------
1 | #include "bbox.h"
2 |
3 | BBox::BBox(const Vec3 &min, const Vec3 &max) {
4 | this->min = Vec3(Min(min.x, max.x), Min(min.y, max.y), Min(min.z, max.z));
5 | this->max = Vec3(Max(min.x, max.x), Max(min.y, max.y), Max(min.z, max.z));
6 | }
7 |
8 | bool BBox::Intersect(const Ray &ray, float *mint, float *maxt) {
9 | float t0 = ray.mint;
10 | float t1 = ray.maxt;
11 | for(int i = 0; i < 3; ++i) {
12 | float invRayDir = 1.0f / ray.d[i];
13 | float tNear = (min[i] - ray.o[i]) * invRayDir;
14 | float tFar = (max[i] - ray.o[i]) * invRayDir;
15 | if(tNear > tFar) {
16 | float tmp = tNear;
17 | tNear = tFar;
18 | tFar = tmp;
19 | }
20 | t0 = tNear > t0 ? tNear : t0;
21 | t1 = tFar < t1 ? tFar : t1;
22 | if(t0 > t1) return false;
23 | }
24 | if(mint) *mint = t0;
25 | if(maxt) *maxt = t1;
26 | return true;
27 | }
28 |
29 | Dimension BBox::Extent() {
30 | Vec3 diagonal = min - max;
31 | if(diagonal.x > diagonal.y && diagonal.x > diagonal.z)
32 | return DIM_X;
33 | else if(diagonal.y > diagonal.z)
34 | return DIM_Y;
35 | else
36 | return DIM_Z;
37 | }
38 |
39 | BBox Union(const BBox &box1, const BBox &box2) {
40 | BBox box;
41 | box.min.x = Min(box1.min.x, box2.min.x);
42 | box.min.y = Min(box1.min.y, box2.min.y);
43 | box.min.z = Min(box1.min.z, box2.min.z);
44 | box.max.x = Max(box1.max.x, box2.max.x);
45 | box.max.y = Max(box1.max.y, box2.max.y);
46 | box.max.z = Max(box1.max.z, box2.max.z);
47 | return box;
48 | }
49 |
50 | BBox Union(const BBox &b, const Vec3 &p) {
51 | BBox box;
52 | box.min.x = Min(b.min.x, p.x);
53 | box.min.y = Min(b.min.y, p.y);
54 | box.min.z = Min(b.min.z, p.z);
55 | box.max.x = Max(b.max.x, p.x);
56 | box.max.y = Max(b.max.y, p.y);
57 | box.max.z = Max(b.max.z, p.z);
58 | return box;
59 | }
60 |
61 |
--------------------------------------------------------------------------------
/src/pathtracer/bbox.h:
--------------------------------------------------------------------------------
1 | #ifndef __BBOX_H__
2 | #define __BBOX_H__
3 |
4 | #include "config.h"
5 | #include "ray.h"
6 |
7 | enum Dimension { DIM_X, DIM_Y, DIM_Z };
8 |
9 | class BBox {
10 | public:
11 | Vec3 min, max;
12 | BBox() {};
13 | BBox(const Vec3 &min, const Vec3 &max);
14 | bool Intersect(const Ray &ray, float *mint, float *maxt);
15 | Dimension Extent();
16 |
17 | friend BBox Union(const BBox &box1, const BBox &box2);
18 | friend BBox Union(const BBox &b, const Vec3 &p);
19 | };
20 |
21 | BBox Union(const BBox &box1, const BBox &box2);
22 | BBox Union(const BBox &b, const Vec3 &p);
23 |
24 | #endif
25 |
--------------------------------------------------------------------------------
/src/pathtracer/camera.cpp:
--------------------------------------------------------------------------------
1 | #include "camera.h"
2 |
3 | Camera::Camera() {
4 | lensRadius = 0.0f;
5 | focalDistance = 0.0f;
6 | }
7 |
8 | Camera::Camera(Vec3 &pos, Vec2 &resolution, float lensRad, float focal)
9 | : cp(pos), lensRadius(lensRad), focalDistance(focal) {
10 | film = new PPMImage(resolution.x, resolution.y);
11 | }
12 |
13 | Camera::~Camera() {
14 | if(film != NULL)
15 | delete film;
16 | }
17 |
18 | void Camera::LookAt(const Vec3 &p) {
19 | Vec3 up = Vec3::Up();
20 | cd = (p - cp).Normalize();
21 | cr = cd.Cross(up).Normalize();
22 | cu = cr.Cross(cd).Normalize();
23 | }
24 |
25 | float Camera::getLensRadius() const {
26 | return lensRadius;
27 | }
28 |
29 | float Camera::getFocalDistance() const {
30 | return focalDistance;
31 | }
32 |
33 | Vec2 Camera::SampleLens() const {
34 | Vec2 uv;
35 | uv.x = (2.0 * rand_0_1() - 1.0) * lensRadius;
36 | uv.y = (2.0 * rand_0_1() - 1.0) * lensRadius;
37 | return uv;
38 | }
39 |
40 | Ray Camera::PrimaryRay(const Vec2& sp) const {
41 | Vec2 p = -2.0f * sp + 1.0f;
42 | Vec3 rd = (cr * p.x + cu * p.y + cd).Normalize();
43 | Ray r = Ray(cp, rd);
44 | return r;
45 | }
46 |
--------------------------------------------------------------------------------
/src/pathtracer/camera.h:
--------------------------------------------------------------------------------
1 | #ifndef __CAMERA_H__
2 | #define __CAMERA_H__
3 |
4 | #include "ray.h"
5 | #include "config.h"
6 | #include "helpers.h"
7 |
8 | class Camera {
9 | public:
10 | Camera();
11 | Camera(Vec3 &pos, Vec2 &resolution, float lensRadius, float focalDistance);
12 | ~Camera();
13 | void LookAt(const Vec3 &p);
14 |
15 | Vec3 GetRight() const { return cr; }
16 | Vec3 GetUp() const { return cu; }
17 | Vec3 GetDir() const { return cd; }
18 | Vec3 GetPos() const { return cp; }
19 |
20 | Ray PrimaryRay(const Vec2& sp) const;
21 | PPMImage* Film() const { return film; }
22 | Vec2 SampleLens() const;
23 | float getLensRadius() const;
24 | float getFocalDistance() const;
25 |
26 | private:
27 | Vec3 cp;
28 | Vec3 cd;
29 | Vec3 cr;
30 | Vec3 cu;
31 | PPMImage *film;
32 | float lensRadius;
33 | float focalDistance;
34 | };
35 |
36 | #endif
37 |
--------------------------------------------------------------------------------
/src/pathtracer/color.h:
--------------------------------------------------------------------------------
1 | #ifndef __COLOR_H__
2 | #define __COLOR_H__
3 |
4 | #include "config.h"
5 | typedef Vec3 Color;
6 |
7 | #endif
8 |
--------------------------------------------------------------------------------
/src/pathtracer/config.h:
--------------------------------------------------------------------------------
1 | #ifndef __CONFIG_H__
2 | #define __CONFIG_H__
3 |
4 | #include
5 | #include
6 |
7 | #include "coremaths.h"
8 | #include "netpbmloader.h"
9 | #include "ppmimage.h"
10 | #include "pathtracer.h"
11 |
12 | using namespace std;
13 |
14 | #define AA_MAX_DEPTH 1
15 |
16 | #endif
17 |
--------------------------------------------------------------------------------
/src/pathtracer/helpers.h:
--------------------------------------------------------------------------------
1 | #ifndef __HELPERS_H__
2 | #define __HELPERS_H__
3 |
4 | inline float rand_0_1() {
5 | return (float) rand() / RAND_MAX;
6 | }
7 |
8 | #endif
9 |
--------------------------------------------------------------------------------
/src/pathtracer/intersection.h:
--------------------------------------------------------------------------------
1 | #ifndef __INTERSECTION_H__
2 | #define __INTERSECTION_H__
3 |
4 | #include "config.h"
5 |
6 | class Object;
7 |
8 | class Intersection {
9 | public:
10 | Intersection() : t(0.0), obj(NULL) {}
11 |
12 | inline friend ostream& operator<<(ostream& o, const Intersection& isect) {
13 | o << "Intersection at " << isect.spos << ", t: " << isect.t << endl;
14 | o << " n: " << isect.n << endl;
15 | o << " p: " << isect.p;
16 | return o;
17 | }
18 |
19 | float t;
20 | Object *obj;
21 | Vec2 spos;
22 | Vec3 n;
23 | Vec3 p;
24 | };
25 |
26 | #endif
27 |
--------------------------------------------------------------------------------
/src/pathtracer/material.h:
--------------------------------------------------------------------------------
1 | #ifndef __MATERIAL_H__
2 | #define __MATERIAL_H__
3 |
4 | enum MaterialType {
5 | E_DIFFUSE,
6 | E_SPECULAR,
7 | E_REFRACT
8 | };
9 |
10 | inline MaterialType MaterialByChar(char material) {
11 | switch(material) {
12 | case 'd': return E_DIFFUSE;
13 | case 's': return E_SPECULAR;
14 | case 'r': return E_REFRACT;
15 | default: return (MaterialType) -1;
16 | }
17 | }
18 |
19 | #endif
20 |
--------------------------------------------------------------------------------
/src/pathtracer/object.h:
--------------------------------------------------------------------------------
1 | #ifndef __PRIMITIVE_H__
2 | #define __PRIMITIVE_H__
3 |
4 | #include "ray.h"
5 | #include "intersection.h"
6 | #include "material.h"
7 | #include "color.h"
8 | #include "config.h"
9 | #include "bbox.h"
10 |
11 | class Object {
12 | public:
13 | Object(Vec3 pos, Color col, Color emis) :
14 | position(pos), color(col), emission(emis) {}
15 | virtual bool Intersect(const Ray &ray, Intersection *isect) = 0;
16 | virtual ~Object() {}
17 | virtual string Description() const = 0;
18 | Vec3 virtual Normal(Vec3 p, Vec3 dir) const = 0;
19 | BBox virtual Bounds() const = 0;
20 |
21 | bool Emit() const {
22 | return emission.r > 0 || emission.g > 0 || emission.b > 0;
23 | }
24 |
25 | void FillIntersection(Intersection* isect, float t, const Ray& ray) {
26 | isect->t = t;
27 | isect->obj = this;
28 | isect->p = ray(t);
29 | isect->n = Normal(isect->p, ray.d);
30 | }
31 |
32 | Vec3 position;
33 | Color color;
34 | Color emission;
35 | MaterialType material;
36 |
37 | inline friend ostream& operator<<(ostream& o, const Object& obj) {
38 | o << obj.Description() << endl;
39 | o << "Position: " << obj.position << endl;
40 | o << "Color: " << obj.color << endl;
41 | o << "Material: ";
42 | switch(obj.material) {
43 | case E_DIFFUSE: o << "E_DIFFUSE" << endl; break;
44 | case E_REFRACT: o << "E_REFRACT" << endl; break;
45 | case E_SPECULAR: o << "E_SPECULAR" << endl; break;
46 | }
47 | return o;
48 | }
49 |
50 | private:
51 | Matrix4 transform;
52 | };
53 |
54 | #endif
55 |
--------------------------------------------------------------------------------
/src/pathtracer/objparser.cpp:
--------------------------------------------------------------------------------
1 | #include "objparser.h"
2 |
3 | void ObjParser::Parse(string objfile, Scene* scene, Vec3 pos, Vec3 col, Vec3 emis, MaterialType material) const {
4 | ifstream file(objfile.c_str(), ios::in);
5 | if(!file) {
6 | cerr << "Can't open file " << objfile << endl;
7 | return;
8 | }
9 |
10 | int lines = 0;
11 | while(file.ignore(std::numeric_limits::max(), '\n')) {
12 | ++lines;
13 | }
14 | file.close();
15 |
16 | ifstream f(objfile.c_str(), ios::in);
17 |
18 | cout << "Loading " << objfile << ".. " << endl;
19 |
20 | string token;
21 | vector vertices;
22 | int currentLine = 0;
23 |
24 | while(!f.eof()) {
25 | f >> token;
26 |
27 | if(token == "#") {
28 | f.ignore(std::numeric_limits::max(), '\n');
29 | continue;
30 | } else if(token == "v") { // vertex
31 | Vec3 vertex;
32 | f >> vertex.x >> vertex.y >> vertex.z;
33 | vertices.push_back(vertex);
34 | } else if(token == "vt") { // tex coord
35 | } else if(token == "vn") { // vertex normal
36 | } else if(token == "f") { // face
37 | string faceLine;
38 | getline(f, faceLine);
39 |
40 | for(unsigned int i = 0; i < faceLine.length(); ++i) {
41 | if(faceLine[i] == '/') {
42 | faceLine[i] = ' ';
43 | }
44 | }
45 |
46 | stringstream ss(faceLine);
47 | string faceToken;
48 |
49 | Vec3 faceVertex[3];
50 | for(int i = 0; i < 6; ++i) {
51 | ss >> faceToken;
52 | if(faceToken.find_first_not_of("\t\n ") != string::npos) {
53 | if(i % 2 == 0) {
54 | faceVertex[i/2] = vertices[atoi(faceToken.c_str()) - 1];
55 | } else {
56 | // normals
57 | }
58 | }
59 | }
60 | Triangle* triangle = new Triangle(faceVertex[0], faceVertex[1], faceVertex[2], pos, col, emis);
61 | triangle->material = material;
62 | scene->AddObject(triangle);
63 | }
64 | currentLine++;
65 | }
66 | f.close();
67 | }
68 |
--------------------------------------------------------------------------------
/src/pathtracer/objparser.h:
--------------------------------------------------------------------------------
1 | #ifndef __OBJ_PARSER_H__
2 | #define __OBJ_PARSER_H__
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #include "scene.h"
12 | #include "config.h"
13 | #include "triangle.h"
14 |
15 | class ObjParser {
16 | public:
17 | ObjParser() {}
18 | void Parse(string objfile, Scene* scene, Vec3 pos, Vec3 col, Vec3 emis, MaterialType material) const;
19 | };
20 |
21 | #endif
22 |
--------------------------------------------------------------------------------
/src/pathtracer/pathtracer.h:
--------------------------------------------------------------------------------
1 | #ifndef __PATH_TRACER_H__
2 | #define __PATH_TRACER_H__
3 |
4 | #include
5 |
6 | #define VERSION_MAJOR 0
7 | #define VERSION_MINOR 9
8 | #define VERSION_MAINT 2
9 |
10 | inline void PrintVersion() {
11 | std::cout << "VERSION -- " <<
12 | VERSION_MAJOR << "." <<
13 | VERSION_MINOR << "." <<
14 | VERSION_MAINT << std::endl;
15 | }
16 |
17 | inline bool CompareVersion(int vmaj, int vmin, int vmaint) {
18 | return VERSION_MAJOR == vmaj &&
19 | VERSION_MINOR == vmin &&
20 | VERSION_MAINT == vmaint;
21 | }
22 |
23 | #endif
24 |
--------------------------------------------------------------------------------
/src/pathtracer/plane.cpp:
--------------------------------------------------------------------------------
1 | #include "plane.h"
2 |
3 | bool Plane::Intersect(const Ray &ray, Intersection *isect) {
4 | float t = -ray.o.y / ray.d.y;
5 |
6 | if((!isect->obj || (t > 0.0 && t < isect->t)) && t > 0.0) {
7 | FillIntersection(isect, t, ray);
8 | return true;
9 | }
10 |
11 | return false;
12 | }
13 |
14 | Vec3 Plane::Normal(Vec3 p, Vec3 dir) const {
15 | Vec3 n = Vec3(0.0, 1.0, 0.0);
16 | if(n.Dot(dir) > 0.0) {
17 | n = -n;
18 | }
19 | return n;
20 | }
21 |
22 | string Plane::Description() const {
23 | string s = "Plane";
24 | return s;
25 | }
26 |
27 | BBox Plane::Bounds() const {
28 | return BBox();
29 | }
30 |
--------------------------------------------------------------------------------
/src/pathtracer/plane.h:
--------------------------------------------------------------------------------
1 | #ifndef __PLANE_H__
2 | #define __PLANE_H__
3 |
4 | #include "object.h"
5 |
6 | class Plane : public Object {
7 | public:
8 | Plane(Vec3 p, Vec3 col, Vec3 emis) : Object(p, col, emis) {}
9 | ~Plane() {}
10 | bool Intersect(const Ray &ray, Intersection *isect);
11 | string Description() const;
12 | Vec3 Normal(Vec3 p, Vec3 dir) const;
13 | BBox Bounds() const;
14 | };
15 |
16 | #endif
17 |
--------------------------------------------------------------------------------
/src/pathtracer/ray.h:
--------------------------------------------------------------------------------
1 | #ifndef __RAY_H__
2 | #define __RAY_H__
3 |
4 | #include "config.h"
5 |
6 | class Ray {
7 | public:
8 | Ray() : mint(0.f), maxt(INFINITY), depth(0) { }
9 | Ray(const Vec3 &origin, const Vec3 &direction,
10 | float start = 0.0f, float end = INFINITY, int d = 0)
11 | : o(origin), d(direction), mint(start), maxt(end), depth(d) { }
12 |
13 | Vec3 operator()(float t) const { return o + d * t; }
14 |
15 | Vec3 o;
16 | Vec3 d;
17 | mutable float mint;
18 | mutable float maxt;
19 | int depth;
20 |
21 | inline friend ostream& operator<<(ostream& o, const Ray& r) {
22 | o << "ray d: " << r.d << " o: " << r.o;
23 | return o;
24 | }
25 | };
26 |
27 | #endif
28 |
--------------------------------------------------------------------------------
/src/pathtracer/renderer.cpp:
--------------------------------------------------------------------------------
1 | #include "renderer.h"
2 |
3 | Renderer::Renderer(int samples) : sppxl(samples) {
4 | mtx = new mutex();
5 | tasks = new vector();
6 | }
7 |
8 | void Renderer::Init(const PPMImage &film) {
9 | int width = film.GetWidth();
10 | int height = film.GetHeight();
11 | int bwidth = film.GetWidth() / 4;
12 | int bheight = film.GetHeight() / 4;
13 | int id = 0;
14 |
15 | for(int x = 0; x < width; x += bwidth) {
16 | int minx = x;
17 | int maxx = x + bwidth > width ? width : x + bwidth;
18 | for(int y = 0; y < height; y += bheight) {
19 | int miny = y;
20 | int maxy = y + bheight > height ? height : y + bheight;
21 |
22 | // create the new rendering task
23 | Bucket *bucket = new Bucket(minx, miny, maxx, maxy);
24 | RenderingTask *rt = new RenderingTask(bucket, sppxl, Vec2(width, height), ++id, mtx);
25 | tasks->push_back(rt);
26 | }
27 | }
28 |
29 | cout << "Initialized " << tasks->size() << " rendering tasks" << endl;
30 | }
31 |
32 | Renderer::~Renderer() {
33 | vector::iterator it;
34 | for(it = tasks->begin(); it != tasks->end(); it++)
35 | delete *it;
36 | delete tasks;
37 | delete mtx;
38 | }
39 |
40 | void Renderer::Render(Scene *scene) {
41 | thread *threads = new thread[tasks->size()];
42 | int *progress = new int();
43 |
44 | *progress = 0;
45 |
46 | for(unsigned int i = 0; i < tasks->size(); ++i) {
47 | RenderingTask *task = (*tasks)[i];
48 | threads[i] = thread(&RenderingTask::Start, task, scene, progress);
49 | }
50 |
51 | // start threads
52 | for(unsigned int i = 0; i < tasks->size(); ++i) {
53 | threads[i].join();
54 | }
55 |
56 | cout << endl;
57 |
58 | delete[] threads;
59 | delete progress;
60 | }
61 |
--------------------------------------------------------------------------------
/src/pathtracer/renderer.h:
--------------------------------------------------------------------------------
1 | #ifndef __RENDERER_H__
2 | #define __RENDERER_H__
3 |
4 | #include
5 | #include
6 |
7 | #include "renderingtask.h"
8 | #include "scene.h"
9 |
10 | class Renderer {
11 | public:
12 | Renderer(int samples = 1);
13 | ~Renderer();
14 | void Init(const PPMImage &film);
15 | void Render(Scene *scene);
16 |
17 | private:
18 | vector *tasks;
19 | int sppxl;
20 | mutex *mtx;
21 | };
22 |
23 | #endif
24 |
--------------------------------------------------------------------------------
/src/pathtracer/renderingtask.cpp:
--------------------------------------------------------------------------------
1 | #include "renderingtask.h"
2 |
3 | RenderingTask::~RenderingTask() {
4 | delete bucket;
5 | }
6 |
7 | void RenderingTask::Start(Scene* scene, int *progress) {
8 | PPMImage *film = scene->GetCamera()->Film();
9 |
10 | int width = film->GetWidth();
11 | int height = film->GetHeight();
12 | float n = (float) width * height;
13 |
14 | float pxw = 1.0 / (float) width;
15 | float pxh = 1.0 / (float) height;
16 | float gamma = 2.2;
17 |
18 | for(int x = bucket->minx; x < bucket->maxx; ++x) {
19 | float xval = x / (float) width;
20 | for(int y = bucket->miny; y < bucket->maxy; ++y) {
21 | float yval = y / (float) height;
22 | Color c;
23 |
24 | for(int s = 0; s < sppxl; ++s)
25 | c += AverageColor(scene, xval, yval, pxw, pxh, 0, sppxl);
26 | c = (c / (float) sppxl);
27 | // gamma correction
28 | c = Vec3(pow(c.r, 1.0 / gamma), pow(c.g, 1.0 / gamma), pow(c.b, 1.0 / gamma));
29 |
30 | (*film)(x, y) = Color::VClamp(c, 0.0, 1.0) * 255.0;
31 | *progress = *progress + 1;
32 | }
33 | mtx->lock();
34 | fprintf(stdout, "\rProgress %5.2f%%", 100.0 * (float)*progress / n);
35 | mtx->unlock();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/pathtracer/renderingtask.h:
--------------------------------------------------------------------------------
1 | #ifndef __RENDERING_TASK_H__
2 | #define __RENDERING_TASK_H__
3 |
4 | #include
5 |
6 | #include "config.h"
7 | #include "shading.h"
8 | #include "helpers.h"
9 | #include "scene.h"
10 |
11 | struct Bucket {
12 | Bucket(int mix, int miy, int max, int may) :
13 | minx(mix), miny(miy), maxx(max), maxy(may) {}
14 | int minx, miny;
15 | int maxx, maxy;
16 | };
17 |
18 | class RenderingTask {
19 | public:
20 | RenderingTask(Bucket* bckt, int samplesppx, Vec2 imgSize, int identitifier, mutex* mutx)
21 | : bucket(bckt), sppxl(samplesppx), size(imgSize), id(identitifier), mtx(mutx) {}
22 | ~RenderingTask();
23 | void Start(Scene* scene, int *progress);
24 |
25 | private:
26 | Bucket *bucket;
27 | int sppxl;
28 | Vec2 size;
29 | int id;
30 | mutex *mtx;
31 | };
32 |
33 | #endif
34 |
--------------------------------------------------------------------------------
/src/pathtracer/scene.cpp:
--------------------------------------------------------------------------------
1 | #include "scene.h"
2 |
3 | Scene::Scene(Camera *cam)
4 | : camera(cam) {
5 | objects = new vector