From a9da86327493499f613d6917357cf7b98c50d79e Mon Sep 17 00:00:00 2001 From: Miguel Angel Astor Romero Date: Mon, 27 Mar 2017 13:48:03 -0400 Subject: [PATCH] Photon tracing fixed. --- main.cpp | 18 +++++++-- photon_tracer.cpp | 82 +++++++++++++++++++------------------ photon_tracer.hpp | 5 ++- scenes/scene10.json | 98 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 160 insertions(+), 43 deletions(-) create mode 100644 scenes/scene10.json diff --git a/main.cpp b/main.cpp index aa997f9..184ec22 100644 --- a/main.cpp +++ b/main.cpp @@ -63,6 +63,7 @@ static float g_gamma = 2.2f; static float g_exposure = 0.0f; static size_t g_photons = 15000; static float g_p_sample_radius = 0.01f; +static float g_cone_filter_k = 1.0f; //////////////////////////////////////////// // Main function. @@ -113,7 +114,7 @@ int main(int argc, char ** argv) { } else if(g_tracer == JENSEN) { cout << "Using " << ANSI_BOLD_YELLOW << "Jensen's photon mapping" << ANSI_RESET_STYLE << " with ray tracing." << endl; - p_tracer = new PhotonTracer(g_max_depth, g_p_sample_radius); + p_tracer = new PhotonTracer(g_max_depth, g_p_sample_radius, g_cone_filter_k); if (g_photons_file == NULL && g_caustics_file == NULL) { cout << "Building global photon map with " << ANSI_BOLD_YELLOW << g_photons / 2 << ANSI_RESET_STYLE << " primary photons per light source." << endl; p_tracer->photon_tracing(scn, g_photons / 2); @@ -246,10 +247,12 @@ void print_usage(char ** const argv) { cerr << " -p\tNumber of primary photons per light source." << endl; cerr << " \tDefaults to 15000." << endl; cerr << " -h\tHemisphere radius for photon map sampling (> 0)." << endl; - cerr << " \tDefaults to 0.01f ." << endl; + cerr << " \tDefaults to 0.01f." << endl; cerr << " -k\tFile with photon definitions." << endl; cerr << " \tSkips the photon tracing step using" << endl; cerr << " \tthe photons defined in the specified file." << endl; + cerr << " -l\tCone filter constant." << endl; + cerr << " \tDefaults to 1.0f." << endl; } void parse_args(int argc, char ** const argv) { @@ -263,7 +266,7 @@ void parse_args(int argc, char ** const argv) { exit(EXIT_FAILURE); } - while((opt = getopt(argc, argv, "-:t:s:w:f:o:r:g:e:p:h:k:c:")) != -1) { + while((opt = getopt(argc, argv, "-:t:s:w:f:o:r:g:e:p:h:k:c:l:")) != -1) { switch (opt) { case 1: g_input_file = (char *)malloc((strlen(optarg) + 1) * sizeof(char)); @@ -384,6 +387,15 @@ void parse_args(int argc, char ** const argv) { g_caustics_file = (char *)malloc((strlen(optarg) + 1) * sizeof(char)); strcpy(g_caustics_file, optarg); break; + + case 'l': + g_cone_filter_k = atof(optarg); + if (g_cone_filter_k <= 0.0f) { + cerr << "Cone filter constant must be greater than or equal to 1.0" << endl; + print_usage(argv); + exit(EXIT_FAILURE); + } + break; case ':': cerr << "Option \"-" << static_cast(optopt) << "\" requires an argument." << endl; diff --git a/photon_tracer.cpp b/photon_tracer.cpp index be9772d..b150f6a 100644 --- a/photon_tracer.cpp +++ b/photon_tracer.cpp @@ -32,7 +32,7 @@ using namespace glm; PhotonTracer::~PhotonTracer() { } vec3 PhotonTracer::trace_ray(Ray & r, Scene * s, unsigned int rec_level) const { - float t, _t, radius, red, green, blue, kr, w; + float t, _t, red, green, blue, kr, radius; Figure * _f; vec3 n, color, i_pos, ref, dir_diff_color, dir_spec_color, p_contrib; Ray mv_r, sr, rr; @@ -120,28 +120,31 @@ vec3 PhotonTracer::trace_ray(Ray & r, Scene * s, unsigned int rec_level) const { // mn = Vec3(i_pos.x - radius, i_pos.y - radius, i_pos.z - radius); // mx = Vec3(i_pos.x + radius, i_pos.y + radius, i_pos.z + radius); // } + + radius = m_h_radius; m_photon_map.find_by_distance(photons, i_pos, n, m_h_radius, 1000); + while(photons.size() == 0 && radius < 5.0) { + radius *= 2; + m_photon_map.find_by_distance(photons, i_pos, n, m_h_radius, 1000); + } + + radius = m_h_radius; m_caustics_map.find_by_distance(caustics, i_pos, n, m_h_radius, 1000); + while(caustics.size() == 0 && radius < 5.0) { + radius *= 2; + m_caustics_map.find_by_distance(caustics, i_pos, n, m_h_radius, 1000); + } photons.insert(photons.end(), caustics.begin(), caustics.end()); for (Photon p : photons) { - w = max(0.0f, -dot(n, -p.direction.toVec3())); - w *= (1.0f - m_h_radius) / 25.0f; p.getColor(red, green, blue); - p_contrib += vec3(red, green, blue) * w; + p_contrib += vec3(red, green, blue); } + + p_contrib /= (1.0f - (2.0f / (3.0f * m_cone_filter_k))) * pi() * (radius * radius); - // for (Photon p : photons) { - // p.getColor(red, green, blue); - // p_contrib += vec3(red, green, blue); - // } - // for (Photon p : caustics) { - // p.getColor(red, green, blue); - // p_contrib += vec3(red, green, blue); - // } - // p_contrib *= (1.0f / pi()) / (m_h_radius * m_h_radius); - // color += (1.0f - _f->m_mat->m_rho) * (((dir_diff_color + p_contrib) * (_f->m_mat->m_diffuse / pi())) + - // (_f->m_mat->m_specular * dir_spec_color)); + // color += (1.0f - _f->m_mat->m_rho) * ((dir_diff_color * (_f->m_mat->m_diffuse / pi())) + + // (_f->m_mat->m_specular * dir_spec_color) + p_contrib); color += (1.0f - _f->m_mat->m_rho) * p_contrib; // Determine the specular reflection color. @@ -337,7 +340,10 @@ void PhotonTracer::trace_photon(Photon & ph, Scene * s, const unsigned int rec_l if (!_f->m_mat->m_refract){ #pragma omp critical { - m_photon_map.addPhoton(ph); + p_pos = Vec3(i_pos.x, i_pos.y, i_pos.z); + p_dir = Vec3(-ph.direction.x, -ph.direction.y, -ph.direction.z); + photon = Photon(p_pos, p_dir, red, green, blue, ph.ref_index); + m_photon_map.addPhoton(photon); } r1 = random01(); @@ -351,16 +357,16 @@ void PhotonTracer::trace_photon(Photon & ph, Scene * s, const unsigned int rec_l photon = Photon(p_pos, p_dir, color.r, color.g, color.b, ph.ref_index); if (rec_level < m_max_depth) - trace_photon(photon, s, rec_level + 1); + trace_photon(photon, s, rec_level + 1); if (_f->m_mat->m_rho > 0.0f && rec_level < m_max_depth) { - color = (_f->m_mat->m_rho) * vec3(red, green, blue); - i_pos += n * BIAS; - p_pos = Vec3(i_pos.x, i_pos.y, i_pos.z); - ph_dir = normalize(reflect(vec3(ph.direction.x, ph.direction.y, ph.direction.z), n)); - p_dir = Vec3(ph_dir.x, ph_dir.y, ph_dir.z); - photon = Photon(p_pos, p_dir, color.r, color.g, color.b, ph.ref_index); - trace_photon(photon, s, rec_level + 1); + color = (_f->m_mat->m_rho) * vec3(red, green, blue); + i_pos += n * BIAS; + p_pos = Vec3(i_pos.x, i_pos.y, i_pos.z); + ph_dir = normalize(reflect(vec3(ph.direction.x, ph.direction.y, ph.direction.z), n)); + p_dir = Vec3(ph_dir.x, ph_dir.y, ph_dir.z); + photon = Photon(p_pos, p_dir, color.r, color.g, color.b, ph.ref_index); + trace_photon(photon, s, rec_level + 1); } } else if (_f->m_mat->m_refract && rec_level < m_max_depth) { @@ -370,24 +376,24 @@ void PhotonTracer::trace_photon(Photon & ph, Scene * s, const unsigned int rec_l // Trace the reflected photon. if (kr > 0.0f) { - color = kr * vec3(red, green, blue); - i_pos += n * BIAS; - p_pos = Vec3(i_pos.x, i_pos.y, i_pos.z); - ph_dir = normalize(reflect(vec3(ph.direction.x, ph.direction.y, ph.direction.z), n)); - p_dir = Vec3(ph_dir.x, ph_dir.y, ph_dir.z); - photon = Photon(p_pos, p_dir, color.r, color.g, color.b, ph.ref_index); - trace_photon(photon, s, rec_level + 1); + color = kr * vec3(red, green, blue); + i_pos += n * BIAS; + p_pos = Vec3(i_pos.x, i_pos.y, i_pos.z); + ph_dir = normalize(reflect(vec3(ph.direction.x, ph.direction.y, ph.direction.z), n)); + p_dir = Vec3(ph_dir.x, ph_dir.y, ph_dir.z); + photon = Photon(p_pos, p_dir, color.r, color.g, color.b, ph.ref_index); + trace_photon(photon, s, rec_level + 1); } // Trace the transmitted photon. if (kr < 1.0f) { - color = (1.0f - kr) * vec3(red, green, blue); - i_pos -= n * (2 * BIAS); - p_pos = Vec3(i_pos.x, i_pos.y, i_pos.z); - ph_dir = normalize(refract(vec3(ph.direction.x, ph.direction.y, ph.direction.z), n, ph.ref_index / _f->m_mat->m_ref_index)); - p_dir = Vec3(ph_dir.x, ph_dir.y, ph_dir.z); - photon = Photon(p_pos, p_dir, color.r, color.g, color.b, _f->m_mat->m_ref_index); - trace_photon(photon, s, rec_level + 1); + color = (1.0f - kr) * vec3(red, green, blue); + i_pos -= n * (2 * BIAS); + p_pos = Vec3(i_pos.x, i_pos.y, i_pos.z); + ph_dir = normalize(refract(vec3(ph.direction.x, ph.direction.y, ph.direction.z), n, ph.ref_index / _f->m_mat->m_ref_index)); + p_dir = Vec3(ph_dir.x, ph_dir.y, ph_dir.z); + photon = Photon(p_pos, p_dir, color.r, color.g, color.b, _f->m_mat->m_ref_index); + trace_photon(photon, s, rec_level + 1); } } } diff --git a/photon_tracer.hpp b/photon_tracer.hpp index 96afc8f..b9c6538 100644 --- a/photon_tracer.hpp +++ b/photon_tracer.hpp @@ -7,8 +7,8 @@ class PhotonTracer: public Tracer { public: - PhotonTracer(): Tracer(), m_h_radius(0.5f) { } - PhotonTracer(unsigned int max_depth, float _r = 0.5f): Tracer(max_depth), m_h_radius(_r) { }; + PhotonTracer(): Tracer(), m_h_radius(0.5f), m_cone_filter_k(1.0f) { } + PhotonTracer(unsigned int max_depth, float _r = 0.5f, float _k = 1.0f): Tracer(max_depth), m_h_radius(_r), m_cone_filter_k(_k < 1.0f ? 1.0f : _k) { }; virtual ~PhotonTracer(); virtual vec3 trace_ray(Ray & r, Scene * s, unsigned int rec_level) const; @@ -18,6 +18,7 @@ public: void build_photon_map(const bool caustics = false); private: float m_h_radius; + float m_cone_filter_k; kdTree m_photon_map; kdTree m_caustics_map; void trace_photon(Photon & ph, Scene * s, const unsigned int rec_level); diff --git a/scenes/scene10.json b/scenes/scene10.json new file mode 100644 index 0000000..945ecd6 --- /dev/null +++ b/scenes/scene10.json @@ -0,0 +1,98 @@ +{ + "camera": { + "eye": [0.0, 0.0, 1.0], + "look": [0.0, 0.0, -1.0], + "left": [-1.0, 0.0, 0.0] + }, + + "point_light": { + "position": [0.0, 0.9, -1.0] + }, + + "sphere": { + "position": [-0.4, -0.75, -0.65], + "radius": 0.25, + "material": { + "diffuse": [1.0, 1.0, 1.0], + "rho": 0.4 + } + }, + + "sphere": { + "position": [-0.75, -0.5, -1.5], + "radius": 0.5, + "material": { + "diffuse": [0.0, 0.0, 0.0], + "rho": 1.0 + } + }, + + "sphere": { + "position": [1.0, -0.5, -1.1], + "radius": 0.5, + "material": { + "diffuse": [1.0, 1.0, 0.0], + "transmissive": true, + "ref_index": 1.33 + } + }, + + "plane": { + "position": [0.0, -1.0, 0.0], + "normal": [0.0, 1.0, 0.0], + "material": { + "diffuse": [1.0, 1.0, 1.0], + "specular": [0.0, 0.0, 0.0], + "transmissive": true + } + }, + + "plane": { + "position": [-2.0, 0.0, 0.0], + "normal": [1.0, 0.0, 0.0], + "material": { + "diffuse": [1.0, 0.0, 0.0], + "specular": [0.0, 0.0, 0.0] + } + }, + + "plane": { + "position": [2.0, 0.0, 0.0], + "normal": [-1.0, 0.0, 0.0], + "material": { + "diffuse": [0.0, 0.0, 1.0], + "transmissive": true, + "specular": [0.0, 0.0, 0.0] + } + }, + + "plane": { + "position": [0.0, 1.0, 0.0], + "normal": [0.0, -1.0, 0.0], + "material": { + "diffuse": [0.0, 1.0, 1.0], + "transmissive": true, + "specular": [0.0, 0.0, 0.0] + } + }, + + "plane": { + "position": [0.0, 0.0, -2.0], + "normal": [0.0, 0.0, 1.0], + "material": { + "diffuse": [1.0, 0.0, 1.0], + "transmissive": true, + "specular": [0.0, 0.0, 0.0] + } + }, + + "plane": { + "position": [0.0, 0.0, 1.1], + "normal": [0.0, 0.0, -1.0], + "material": { + "diffuse": [1.0, 1.0, 0.0], + "transmissive": true, + "specular": [0.0, 0.0, 0.0] + } + } +}