├── .gitignore
├── CMakeLists.txt
├── src
├── inc
│ ├── base.hpp
│ ├── base
│ │ ├── ray.hpp
│ │ ├── rng.hpp
│ │ ├── math.hpp
│ │ ├── object.hpp
│ │ ├── direction.hpp
│ │ ├── scene.hpp
│ │ ├── parallel.hpp
│ │ ├── intersection.hpp
│ │ ├── distribution.hpp
│ │ ├── sphere.hpp
│ │ ├── image.hpp
│ │ ├── material.hpp
│ │ ├── math
│ │ │ ├── vec4.hpp
│ │ │ ├── vec3.hpp
│ │ │ └── mat4.hpp
│ │ ├── camera.hpp
│ │ └── kd_tree.hpp
│ └── sample
│ │ ├── our.hpp
│ │ └── our
│ │ ├── path
│ │ ├── cache-impl.hpp
│ │ ├── camera_path-impl.hpp
│ │ └── light_path-impl.hpp
│ │ ├── path_vertex.hpp
│ │ ├── path.hpp
│ │ └── renderer-impl.hpp
└── main.cpp
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Project exclude paths
2 | /cmake-build-debug/
3 | /cmake-build-release/
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required( VERSION 3.15 )
2 | project( simple_ris_bpt )
3 |
4 | set( CMAKE_CXX_STANDARD 17 )
5 |
6 | file( GLOB HEADER_FILES src/inc/*.hpp src/inc/*/*.hpp src/inc/*/*/*.hpp src/inc/*/*/*/*.hpp )
7 | file( GLOB SOURCE_FILES src/main.cpp )
8 | add_executable( ${PROJECT_NAME} ${HEADER_FILES} ${SOURCE_FILES} )
9 | target_link_libraries( ${PROJECT_NAME} )
--------------------------------------------------------------------------------
/src/inc/base.hpp:
--------------------------------------------------------------------------------
1 |
2 | #pragma once
3 |
4 | #ifndef BASE_HPP
5 | #define BASE_HPP
6 |
7 | #include"base/ray.hpp"
8 | #include"base/rng.hpp"
9 | #include"base/math.hpp"
10 | #include"base/scene.hpp"
11 | #include"base/image.hpp"
12 | #include"base/sphere.hpp"
13 | #include"base/object.hpp"
14 | #include"base/camera.hpp"
15 | #include"base/kd_tree.hpp"
16 | #include"base/parallel.hpp"
17 | #include"base/distribution.hpp"
18 | #include"base/intersection.hpp"
19 | #include"base/material.hpp"
20 |
21 | #endif
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # simple_ris_bpt
2 | A simple implementation of [resampling-aware weighting functions for bidirectional path tracing using multiple light sub-paths](https://doi.org/10.1145/3338994)
3 | (K. Nabata, K. Iwasaki, Y. Dobashi, ACM Transactions on Graphics, Vol. 39, No. 2, Article. 15, pp.1-11, 2020)
4 |
5 | ### Project Website
6 |
7 |
8 |
9 | ### How to Build
10 |
11 | We use [CMake](https://cmake.org/) to build this project.
12 | We have tested this project on Windows + Visual Studio 2019 and Mac + CLion.
13 | For Windows+VS2019, create VS project through CMake.
14 |
15 |
16 | ### Disclaimer
17 | This project is intended to assist in re-implementing our method.
18 |
--------------------------------------------------------------------------------
/src/inc/base/ray.hpp:
--------------------------------------------------------------------------------
1 |
2 | #pragma once
3 |
4 | #ifndef RAY_HPP
5 | #define RAY_HPP
6 |
7 | #include"math.hpp"
8 |
9 | ///////////////////////////////////////////////////////////////////////////////////////////////////
10 | //ray
11 | ///////////////////////////////////////////////////////////////////////////////////////////////////
12 |
13 | class ray
14 | {
15 | public:
16 |
17 | //constructor (o: origin, d: direction (unit vector), t: distance from origin to intersection point)
18 | ray(const vec3 &o, const vec3 &d, const float t = FLT_MAX) : m_o(o), m_d(d), m_t(t)
19 | {
20 | }
21 |
22 | const vec3 &o() const
23 | {
24 | return m_o;
25 | }
26 | const vec3 &d() const
27 | {
28 | return m_d;
29 | }
30 |
31 | float t() const
32 | {
33 | return m_t;
34 | }
35 | float &t()
36 | {
37 | return m_t;
38 | }
39 |
40 | float t_min() const
41 | {
42 | return 1e-3f;
43 | }
44 |
45 | private:
46 |
47 | vec3 m_o;
48 | vec3 m_d;
49 | float m_t;
50 | };
51 |
52 | ///////////////////////////////////////////////////////////////////////////////////////////////////
53 |
54 | #endif
55 |
--------------------------------------------------------------------------------
/src/inc/base/rng.hpp:
--------------------------------------------------------------------------------
1 |
2 | #pragma once
3 |
4 | #ifndef RANDOM_NUMBER_GENERATOR_HPP
5 | #define RANDOM_NUMBER_GENERATOR_HPP
6 |
7 | #include
8 |
9 | ///////////////////////////////////////////////////////////////////////////////////////////////////
10 | //random_number_generator
11 | ///////////////////////////////////////////////////////////////////////////////////////////////////
12 |
13 | class random_number_generator
14 | {
15 | public:
16 |
17 | //constructor
18 | random_number_generator(const size_t seed = std::mt19937_64::default_seed) : m_engine(seed)
19 | {
20 | }
21 |
22 | //generate uniform random variable [0,1)
23 | float generate_uniform_real()
24 | {
25 | const float tmp = std::generate_canonical(m_engine);
26 | if(tmp < 1){
27 | return tmp;
28 | }else{
29 | return 1 - FLT_EPSILON * 0.5f;
30 | }
31 | }
32 |
33 | //generate uniform random variable of integers in [min,max]
34 | size_t generate_uniform_int(const size_t min, const size_t max)
35 | {
36 | return min + (m_engine() % (max - min + 1));
37 | }
38 |
39 | private:
40 |
41 | std::mt19937_64 m_engine;
42 | };
43 |
44 | ///////////////////////////////////////////////////////////////////////////////////////////////////
45 |
46 | #endif
47 |
--------------------------------------------------------------------------------
/src/inc/base/math.hpp:
--------------------------------------------------------------------------------
1 |
2 | #pragma once
3 |
4 | #ifndef MATH_HPP
5 | #define MATH_HPP
6 |
7 | #include
8 | #include
9 |
10 | #include"math/vec3.hpp"
11 | #include"math/vec4.hpp"
12 | #include"math/mat4.hpp"
13 |
14 | ///////////////////////////////////////////////////////////////////////////////////////////////////
15 | //function definitions
16 | ///////////////////////////////////////////////////////////////////////////////////////////////////
17 |
18 | inline float PI()
19 | {
20 | return 3.14159265358979323846f;
21 | }
22 |
23 | ///////////////////////////////////////////////////////////////////////////////////////////////////
24 |
25 | //convert radian to degree
26 | inline float conv_rad_to_deg(const float rad)
27 | {
28 | return rad * (180 / PI());
29 | }
30 |
31 | ///////////////////////////////////////////////////////////////////////////////////////////////////
32 |
33 | //convert degree to radian
34 | inline float conv_deg_to_rad(const float deg)
35 | {
36 | return deg * (PI() / 180);
37 | }
38 |
39 | ///////////////////////////////////////////////////////////////////////////////////////////////////
40 |
41 | //clamp val in [min,max]
42 | inline float clamp(const float val, const float min, const float max)
43 | {
44 | return (val < min) ? min : (val > max) ? max : val;
45 | }
46 |
47 | ///////////////////////////////////////////////////////////////////////////////////////////////////
48 |
49 | #endif
50 |
--------------------------------------------------------------------------------
/src/inc/base/object.hpp:
--------------------------------------------------------------------------------
1 |
2 | #pragma once
3 |
4 | #ifndef OBJECT_HPP
5 | #define OBJECT_HPP
6 |
7 | #include"sphere.hpp"
8 | #include"material.hpp"
9 |
10 | ///////////////////////////////////////////////////////////////////////////////////////////////////
11 | //object
12 | ///////////////////////////////////////////////////////////////////////////////////////////////////
13 |
14 | class object
15 | {
16 | public:
17 |
18 | object(const sphere &sph, const material &mtl) : m_sph(sph), m_mtl(mtl)
19 | {
20 | }
21 |
22 | bool calc_intersection(ray &r, intersection &isect) const
23 | {
24 | if(m_sph.calc_intersection(r.o(), r.d(), r.t(), r.t_min(), isect)){
25 | isect = intersection(isect.p(), isect.n(), &m_mtl);
26 | return true;
27 | }else{
28 | return false;
29 | }
30 | }
31 |
32 | bool intersect(const ray &r) const
33 | {
34 | float t_max = r.t();
35 | return m_sph.intersect(r.o(), r.d(), t_max, r.t_min());
36 | }
37 |
38 | sample_point sample(random_number_generator &rng) const
39 | {
40 | sample_point sample = m_sph.sample(rng);
41 | return sample_point(sample.p(), sample.n(), &m_mtl, sample.pdf());
42 | }
43 |
44 | float light_power() const
45 | {
46 | return m_mtl.is_emissive() ? luminance(m_mtl.Me()) * m_sph.area() : 0;
47 | }
48 |
49 | private:
50 |
51 | sphere m_sph;
52 | material m_mtl;
53 | };
54 |
55 | ///////////////////////////////////////////////////////////////////////////////////////////////////
56 |
57 | #endif
58 |
--------------------------------------------------------------------------------
/src/inc/base/direction.hpp:
--------------------------------------------------------------------------------
1 |
2 | #pragma once
3 |
4 | #ifndef DIRECTION_HPP
5 | #define DIRECTION_HPP
6 |
7 | #include"math.hpp"
8 |
9 | ///////////////////////////////////////////////////////////////////////////////////////////////////
10 | //direction
11 | ///////////////////////////////////////////////////////////////////////////////////////////////////
12 |
13 | class direction
14 | {
15 | public:
16 |
17 | //constructor
18 | direction() : m_is_valid()
19 | {
20 | }
21 | direction(const vec3 &w, const vec3 &n) : m_w(w), m_cos(dot(w, n)), m_abs_cos(abs(m_cos))
22 | {
23 | //invalidate directions of grazing angle
24 | m_is_valid = (m_abs_cos >= 1e-6f);
25 | }
26 | explicit direction(const vec3 &w) : m_w(w), m_cos(1), m_abs_cos(1), m_is_valid(true)
27 | {
28 | }
29 |
30 | //return direction
31 | operator vec3() const
32 | {
33 | return assert(is_valid()), m_w;
34 | }
35 | vec3 operator-() const
36 | {
37 | return assert(is_valid()), -m_w;
38 | }
39 |
40 | //return cosine
41 | float cos() const
42 | {
43 | return assert(is_valid()), m_cos;
44 | }
45 | float abs_cos() const
46 | {
47 | return assert(is_valid()), m_abs_cos;
48 | }
49 |
50 | bool in_upper_hemisphere() const
51 | {
52 | return assert(is_valid()), (m_cos > 0);
53 | }
54 | bool in_lower_hemisphere() const
55 | {
56 | return !(in_upper_hemisphere());
57 | }
58 |
59 | bool is_valid() const
60 | {
61 | return m_is_valid;
62 | }
63 | bool is_invalid() const
64 | {
65 | return !(is_valid());
66 | }
67 |
68 | private:
69 |
70 | vec3 m_w;
71 | float m_cos;
72 | float m_abs_cos;
73 | bool m_is_valid;
74 | };
75 |
76 | ///////////////////////////////////////////////////////////////////////////////////////////////////
77 |
78 | #endif
79 |
--------------------------------------------------------------------------------
/src/inc/base/scene.hpp:
--------------------------------------------------------------------------------
1 |
2 | #pragma once
3 |
4 | #ifndef SCENE_HPP
5 | #define SCENE_HPP
6 |
7 | #include"object.hpp"
8 | #include"distribution.hpp"
9 |
10 | ///////////////////////////////////////////////////////////////////////////////////////////////////
11 | //scene
12 | ///////////////////////////////////////////////////////////////////////////////////////////////////
13 |
14 | class scene
15 | {
16 | public:
17 |
18 | scene(std::vector