diff --git a/disk.cpp b/disk.cpp index 0a802d0..a03e145 100644 --- a/disk.cpp +++ b/disk.cpp @@ -1,12 +1,16 @@ -#include +#include +#include #include "disk.hpp" #include "sampling.hpp" +using glm::vec2; using glm::cos; using glm::sin; using glm::dot; -using glm::pi; +using glm::distance; +using glm::cross; +using glm::abs; bool Disk::intersect(Ray & r, float & t) const { float _t; @@ -23,14 +27,15 @@ bool Disk::intersect(Ray & r, float & t) const { } vec3 Disk::sample_at_surface() const { - float theta = random01() * (2.0f * pi()); - float r = glm::sqrt(random01() * m_radius); - float x = r * cos(theta); - float y = r * sin(theta); - float z = 0.0f; - vec3 sample = vec3(x, y, z); - rotate_sample(sample, m_normal); - return sample; + float theta = random01() * pi2; + float r = random01() * m_radius; + vec3 nt, nb; + create_coords_system(m_normal, nt, nb); + float x = m_point.x + (r * cos(theta) * nt.x) + (r * sin(theta) * nb.x); + float y = m_point.y + (r * cos(theta) * nt.y) + (r * sin(theta) * nb.y); + float z = m_point.z + (r * cos(theta) * nt.z) + (r * sin(theta) * nb.z); + + return vec3(x, y, z); } void Disk::calculate_inv_area() { diff --git a/disk.hpp b/disk.hpp index 9076670..7d032dc 100644 --- a/disk.hpp +++ b/disk.hpp @@ -3,25 +3,30 @@ #define DISK_HPP #include +#include #include "plane.hpp" using glm::vec3; using glm::normalize; +using glm::pi; class Disk : public Plane { public: float m_radius; Disk(Material * mat = NULL): Plane(mat), m_radius(1.0f) { + pi2 = 2.0f * pi(); calculate_inv_area(); } Disk(float x, float y, float z, float nx, float ny, float nz, float _r, Material * mat = NULL): Plane(x, y, z, nx, ny, nz, mat), m_radius(_r) { + pi2 = 2.0f * pi(); calculate_inv_area(); } Disk(vec3 _p, vec3 _n, float _r, Material * mat = NULL): Plane(_p, _n, mat), m_radius(_r) { + pi2 = 2.0f * pi(); calculate_inv_area(); } @@ -32,6 +37,9 @@ public: protected: virtual void calculate_inv_area(); + +private: + float pi2; }; diff --git a/disk_area_light.cpp b/disk_area_light.cpp index c4378b2..388b483 100644 --- a/disk_area_light.cpp +++ b/disk_area_light.cpp @@ -5,29 +5,39 @@ #include "ray.hpp" using glm::normalize; - -const float BIAS = 0.000001f; +using glm::dot; vec3 DiskAreaLight::diffuse(vec3 normal, Ray & r, vec3 i_pos, Material & m) const { - float d, att; +float d, att, ln_dot_d, d2, g; vec3 l_dir, ref; l_dir = normalize(direction(i_pos)); - d = distance(i_pos); - att = 1.0f / (m_const_att + (m_lin_att * d) + (m_quad_att * (d * d))); + 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(); - return (att * m.m_brdf->diffuse(l_dir, normal, r, i_pos, m_diffuse)) / m_figure->pdf(); + } else + return vec3(0.0f); } vec3 DiskAreaLight::specular(vec3 normal, Ray & r, vec3 i_pos, Material & m) const { -float d, att; + float d, att, ln_dot_d; vec3 l_dir, ref; l_dir = normalize(direction(i_pos)); - d = distance(i_pos); - att = 1.0f / (m_const_att + (m_lin_att * d) + (m_quad_att * (d * d))); + 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(); - 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) { diff --git a/scenes/scene5.json b/scenes/scene5.json index ca77857..e70c37f 100644 --- a/scenes/scene5.json +++ b/scenes/scene5.json @@ -13,8 +13,9 @@ } }, - "sphere_area_light": { + "disk_area_light": { "position": [0.0, 1.0, -2.0], + "normal": [0.0, -1.0, -2.0], "radius": 0.15, "material": { "emission": [1.0, 1.0, 1.0] diff --git a/scenes/scene6.json b/scenes/scene6.json index 40c72a2..b9b22d1 100644 --- a/scenes/scene6.json +++ b/scenes/scene6.json @@ -1,6 +1,7 @@ { - "sphere_area_light": { + "disk_area_light": { "position": [0.0, 0.75, -1.0], + "normal": [0.0, -1.0, 0.0], "radius": 0.15, "material": { "emission": [1.0, 1.0, 1.0] diff --git a/sphere_area_light.cpp b/sphere_area_light.cpp index 1552fbb..820517f 100644 --- a/sphere_area_light.cpp +++ b/sphere_area_light.cpp @@ -10,7 +10,7 @@ vec3 SphereAreaLight::diffuse(vec3 normal, Ray & r, vec3 i_pos, Material & m) co vec3 l_dir, ref; l_dir = normalize(direction(i_pos)); - ln_dot_d = dot(-m_n_at_last_sample, l_dir); + 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; @@ -28,7 +28,7 @@ vec3 SphereAreaLight::specular(vec3 normal, Ray & r, vec3 i_pos, Material & m) c vec3 l_dir, ref; l_dir = normalize(direction(i_pos)); - ln_dot_d = dot(-m_n_at_last_sample, l_dir); + 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)));