diff --git a/area_light.hpp b/area_light.hpp new file mode 100644 index 0000000..ad0603b --- /dev/null +++ b/area_light.hpp @@ -0,0 +1,86 @@ +#pragma once +#ifndef AREA_LIGHT_HPP +#define AREA_LIGHT_HPP + +#include "light.hpp" + +using glm::length; +using glm::normalize; +using glm::dot; + +class AreaLight: public Light { +public: + float m_const_att; + float m_lin_att; + float m_quad_att; + Figure * m_figure; + + AreaLight(): + Light(AREA), + m_const_att(1.0), + m_lin_att(0.0), + m_quad_att(0.0), + m_figure(NULL), + m_last_sample(vec3()), + m_n_at_last_sample(vec3()) + { } + + AreaLight(Figure * _f, float _c = 1.0, float _l = 0.0, float _q = 0.0): + Light(AREA), + m_const_att(_c), + m_lin_att(_l), + m_quad_att(_q), + m_figure(_f), + m_last_sample(vec3()), + m_n_at_last_sample(vec3()) + { } + + virtual vec3 direction(vec3 point) const { + return normalize(m_last_sample - point); + } + + virtual float distance(vec3 point) const { + return length(m_last_sample - point); + } + + vec3 diffuse(vec3 normal, Ray & r, vec3 i_pos, Material & m) const { + float d, att, ln_dot_d, d2, g; + vec3 l_dir, ref; + + l_dir = normalize(direction(i_pos)); + ln_dot_d = dot(m_n_at_last_sample, l_dir); + if (ln_dot_d > 0.0f) { + d2 = distance(i_pos); + d2 *= d2; + g = ln_dot_d / d2; + d = distance(i_pos); + att = 1.0f / (m_const_att + (m_lin_att * d) + (m_quad_att * (d * d))); + return (att * m.m_brdf->diffuse(l_dir, normal, r, i_pos, m_figure->m_mat->m_emission) * g) / m_figure->pdf(); + + } else + return vec3(0.0f); + } + + vec3 specular(vec3 normal, Ray & r, vec3 i_pos, Material & m) const { + float d, att, ln_dot_d; + vec3 l_dir, ref; + + l_dir = normalize(direction(i_pos)); + ln_dot_d = dot(m_n_at_last_sample, l_dir); + if (ln_dot_d > 0.0f) { + d = distance(i_pos); + att = 1.0f / (m_const_att + (m_lin_att * d) + (m_quad_att * (d * d))); + return (att * m.m_brdf->specular(l_dir, normal, r, i_pos, m_figure->m_mat->m_emission, m.m_shininess)) / m_figure->pdf(); + + } else + return vec3(0.0f); + } + + virtual void sample_at_surface(vec3 point) = 0; + +protected: + vec3 m_last_sample; + vec3 m_n_at_last_sample; +}; + +#endif diff --git a/disk_area_light.cpp b/disk_area_light.cpp index f49bdd1..8a6ee37 100644 --- a/disk_area_light.cpp +++ b/disk_area_light.cpp @@ -1,44 +1,4 @@ -#include -#include - #include "disk_area_light.hpp" -#include "ray.hpp" - -using glm::normalize; -using glm::dot; - -vec3 DiskAreaLight::diffuse(vec3 normal, Ray & r, vec3 i_pos, Material & m) const { -float d, att, ln_dot_d, d2, g; - vec3 l_dir, ref; - - l_dir = normalize(direction(i_pos)); - ln_dot_d = dot(-m_n_at_last_sample, l_dir); - if (ln_dot_d > 0.0f) { - d2 = distance(i_pos); - d2 *= d2; - g = ln_dot_d / d2; - d = distance(i_pos); - att = 1.0f / (m_const_att + (m_lin_att * d) + (m_quad_att * (d * d))); - return (att * m.m_brdf->diffuse(l_dir, normal, r, i_pos, m_diffuse) * g) / m_figure->pdf(); - - } else - return vec3(0.0f); -} - -vec3 DiskAreaLight::specular(vec3 normal, Ray & r, vec3 i_pos, Material & m) const { - float d, att, ln_dot_d; - vec3 l_dir, ref; - - l_dir = normalize(direction(i_pos)); - ln_dot_d = dot(-m_n_at_last_sample, l_dir); - if (ln_dot_d > 0.0f) { - d = distance(i_pos); - att = 1.0f / (m_const_att + (m_lin_att * d) + (m_quad_att * (d * d))); - return (att * m.m_brdf->specular(l_dir, normal, r, i_pos, m_specular, m.m_shininess)) / m_figure->pdf(); - - } else - return vec3(0.0f); -} void DiskAreaLight::sample_at_surface(vec3 point) { Disk * d = static_cast(m_figure); diff --git a/disk_area_light.hpp b/disk_area_light.hpp index 4add376..d205242 100644 --- a/disk_area_light.hpp +++ b/disk_area_light.hpp @@ -2,24 +2,13 @@ #ifndef DISK_AREA_LIGHT_HPP #define DISK_AREA_LIGHT_HPP -#include "light.hpp" +#include "area_light.hpp" #include "disk.hpp" class DiskAreaLight: public AreaLight { public: - float m_const_att; - float m_lin_att; - float m_quad_att; + DiskAreaLight(Disk * _s, float _c = 1.0, float _l = 0.0, float _q = 0.0): AreaLight(static_cast
(_s), _c, _l, _q) { } - DiskAreaLight(Disk * _s, float _c = 1.0, float _l = 0.0, float _q = 0.0): - AreaLight(static_cast
(_s)), - m_const_att(_c), - m_lin_att(_l), - m_quad_att(_q) - { } - - virtual vec3 diffuse(vec3 normal, Ray & r, vec3 i_pos, Material & m) const; - virtual vec3 specular(vec3 normal, Ray & r, vec3 i_pos, Material & m) const; virtual void sample_at_surface(vec3 point); }; diff --git a/light.hpp b/light.hpp index 84309e4..693c07e 100644 --- a/light.hpp +++ b/light.hpp @@ -9,8 +9,6 @@ #include "ray.hpp" using glm::vec3; -using glm::length; -using glm::normalize; class Light { public: @@ -53,29 +51,4 @@ public: virtual vec3 specular(vec3 normal, Ray & r, vec3 i_pos, Material & m) const = 0; }; -class AreaLight: public Light { -public: - Figure * m_figure; - - AreaLight(): Light(AREA), m_figure(NULL), m_last_sample(vec3()), m_n_at_last_sample(vec3()) { } - - AreaLight(Figure * _f): Light(AREA), m_figure(_f), m_last_sample(vec3()), m_n_at_last_sample(vec3()) { } - - virtual vec3 direction(vec3 point) const { - return normalize(m_last_sample - point); - } - - virtual float distance(vec3 point) const { - return length(m_last_sample - point); - } - - virtual vec3 diffuse(vec3 normal, Ray & r, vec3 i_pos, Material & m) const = 0; - virtual vec3 specular(vec3 normal, Ray & r, vec3 i_pos, Material & m) const = 0; - virtual void sample_at_surface(vec3 point) = 0; - -protected: - vec3 m_last_sample; - vec3 m_n_at_last_sample; -}; - #endif diff --git a/path_tracer.cpp b/path_tracer.cpp index 0163842..c06d67f 100644 --- a/path_tracer.cpp +++ b/path_tracer.cpp @@ -4,6 +4,7 @@ #include "path_tracer.hpp" #include "sampling.hpp" +#include "area_light.hpp" using std::numeric_limits; using namespace glm; diff --git a/scenes/scene6.json b/scenes/scene6.json index c421694..8d7318c 100644 --- a/scenes/scene6.json +++ b/scenes/scene6.json @@ -12,7 +12,7 @@ "radius": 0.25, "material": { "diffuse": [1.0, 1.0, 1.0], - "rho": 0.2 + "rho": 0.4 } }, diff --git a/sphere_area_light.cpp b/sphere_area_light.cpp index 820517f..d8891d3 100644 --- a/sphere_area_light.cpp +++ b/sphere_area_light.cpp @@ -1,42 +1,4 @@ #include "sphere_area_light.hpp" -#include "ray.hpp" - -using glm::max; -using glm::dot; -using glm::normalize; - -vec3 SphereAreaLight::diffuse(vec3 normal, Ray & r, vec3 i_pos, Material & m) const { - float d, att, ln_dot_d, d2, g; - vec3 l_dir, ref; - - l_dir = normalize(direction(i_pos)); - ln_dot_d = dot(m_n_at_last_sample, l_dir); - if (ln_dot_d > 0.0f) { - d2 = glm::distance(m_last_sample, i_pos); - d2 *= d2; - g = ln_dot_d / d2; - d = distance(i_pos); - att = 1.0f / (m_const_att + (m_lin_att * d) + (m_quad_att * (d * d))); - return (att * m.m_brdf->diffuse(l_dir, normal, r, i_pos, m_diffuse) * g) / m_figure->pdf(); - - } else - return vec3(0.0f); -} - -vec3 SphereAreaLight::specular(vec3 normal, Ray & r, vec3 i_pos, Material & m) const { - float d, att, ln_dot_d; - vec3 l_dir, ref; - - l_dir = normalize(direction(i_pos)); - ln_dot_d = dot(m_n_at_last_sample, l_dir); - if (ln_dot_d > 0.0f) { - d = distance(i_pos); - att = 1.0f / (m_const_att + (m_lin_att * d) + (m_quad_att * (d * d))); - return (att * m.m_brdf->specular(l_dir, normal, r, i_pos, m_specular, m.m_shininess)) / m_figure->pdf(); - - } else - return vec3(0.0f); -} void SphereAreaLight::sample_at_surface(vec3 point) { Sphere * s = static_cast(m_figure); diff --git a/sphere_area_light.hpp b/sphere_area_light.hpp index 2517838..0d0ed9d 100644 --- a/sphere_area_light.hpp +++ b/sphere_area_light.hpp @@ -2,24 +2,13 @@ #ifndef SPHERE_AREA_LIGHT_HPP #define SPHERE_AREA_LIGHT_HPP -#include "light.hpp" +#include "area_light.hpp" #include "sphere.hpp" class SphereAreaLight: public AreaLight { public: - float m_const_att; - float m_lin_att; - float m_quad_att; + SphereAreaLight(Sphere * _s, float _c = 1.0, float _l = 0.0, float _q = 0.0): AreaLight(static_cast
(_s), _c, _l, _q) { } - SphereAreaLight(Sphere * _s, float _c = 1.0, float _l = 0.0, float _q = 0.0): - AreaLight(static_cast
(_s)), - m_const_att(_c), - m_lin_att(_l), - m_quad_att(_q) - { } - - virtual vec3 diffuse(vec3 normal, Ray & r, vec3 i_pos, Material & m) const; - virtual vec3 specular(vec3 normal, Ray & r, vec3 i_pos, Material & m) const; virtual void sample_at_surface(vec3 point); }; diff --git a/whitted_tracer.cpp b/whitted_tracer.cpp index 1ef13fa..3c56be6 100644 --- a/whitted_tracer.cpp +++ b/whitted_tracer.cpp @@ -4,6 +4,7 @@ #include #include "whitted_tracer.hpp" +#include "area_light.hpp" using std::numeric_limits; using namespace glm;