diff --git a/Makefile b/Makefile index 343b615..029e344 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CXX = g++ TARGET = ray -OBJECTS = main.o disk.o plane.o sphere.o directional_light.o point_light.o tracer.o path_tracer.o whitted_tracer.o +OBJECTS = main.o disk.o plane.o sphere.o directional_light.o point_light.o tracer.o path_tracer.o whitted_tracer.o phong_brdf.o DEPENDS = $(OBJECTS:.o=.d) CXXFLAGS = -ansi -pedantic -Wall -DGLM_FORCE_RADIANS -fopenmp LDLIBS = -lfreeimage diff --git a/brdf.hpp b/brdf.hpp new file mode 100644 index 0000000..14a54c5 --- /dev/null +++ b/brdf.hpp @@ -0,0 +1,20 @@ +#pragma once +#ifndef BRDF_HPP +#define BRDF_HPP + +#include + +#include "ray.hpp" +#include "material.hpp" + +using glm::vec3; + +class BRDF { +public: + virtual ~BRDF() { } + + virtual vec3 diffuse(vec3 light_dir, vec3 surface_normal, Ray & incident_ray, vec3 light_diff_color) const = 0; + virtual vec3 specular(vec3 light_dir, vec3 surface_normal, Ray & incident_ray, vec3 light_spec_color, float shininess) const = 0; +}; + +#endif diff --git a/directional_light.cpp b/directional_light.cpp index 0f8322a..7653087 100644 --- a/directional_light.cpp +++ b/directional_light.cpp @@ -20,23 +20,10 @@ inline float DirectionalLight::distance(vec3 point) { return numeric_limits::max(); } -vec3 DirectionalLight::diffuse(vec3 normal, Ray & r, float t, Material & m) const { - float n_dot_l; - vec3 color; - - n_dot_l = max(dot(normal, m_position), 0.0f); - color += m_diffuse * n_dot_l; - - return color; +vec3 DirectionalLight::diffuse(vec3 normal, Ray & r, vec3 i_pos, Material & m) const { + return m_brdf->diffuse(m_position, normal, r, m_diffuse); } -vec3 DirectionalLight::specular(vec3 normal, Ray & r, float t, Material & m) const { - float r_dot_l; - vec3 color, ref; - - ref = reflect(m_position, normal); - r_dot_l = pow(max(dot(ref, r.m_direction), 0.0f), m.m_shininess); - color += m.m_specular * m_specular * r_dot_l; - - return color; +vec3 DirectionalLight::specular(vec3 normal, Ray & r, vec3 i_pos, Material & m) const { + return m.m_specular * m_brdf->specular(m_position, normal, r, m_specular, m.m_shininess); } diff --git a/directional_light.hpp b/directional_light.hpp index 04cdc1f..b008adf 100644 --- a/directional_light.hpp +++ b/directional_light.hpp @@ -6,22 +6,14 @@ class DirectionalLight: public Light { public: - DirectionalLight() { - m_position = vec3(0.0f); - m_diffuse = vec3(1.0f); - m_specular = vec3(1.0f); - } + DirectionalLight(): Light() { } - DirectionalLight(vec3 _p, vec3 _d, vec3 _s) { - m_position = _p; - m_diffuse = _d; - m_specular = _s; - } + DirectionalLight(BRDF * _brdf, vec3 _p, vec3 _d, vec3 _s): Light(_brdf, _p, _d, _s) { } virtual vec3 direction(vec3 point); virtual float distance(vec3 point); - virtual vec3 diffuse(vec3 normal, Ray & r, float t, Material & m) const; - virtual vec3 specular(vec3 normal, Ray & r, float t, Material & m) const; + 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; }; #endif diff --git a/light.hpp b/light.hpp index 8f05d61..09866a9 100644 --- a/light.hpp +++ b/light.hpp @@ -4,6 +4,8 @@ #include +#include "brdf.hpp" +#include "phong_brdf.hpp" #include "ray.hpp" #include "material.hpp" @@ -11,16 +13,23 @@ using glm::vec3; class Light { public: + BRDF * m_brdf; vec3 m_position; vec3 m_diffuse; vec3 m_specular; - virtual ~Light() { } + Light(): m_brdf(static_cast(new PhongBRDF())), m_position(vec3(0.0f)), m_diffuse(vec3(1.0f)), m_specular(vec3(1.0f)) { } + + Light(BRDF * _brdf, vec3 _p, vec3 _d, vec3 _s): m_brdf(_brdf), m_position(_p), m_diffuse(_d), m_specular(_s) { } + + virtual ~Light() { + delete m_brdf; + } virtual vec3 direction(vec3 point) = 0; virtual float distance(vec3 point) = 0; - virtual vec3 diffuse(vec3 normal, Ray & r, float t, Material & m) const = 0; - virtual vec3 specular(vec3 normal, Ray & r, float t, Material & m) const = 0; + 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; }; #endif diff --git a/main.cpp b/main.cpp index 86ce74f..3e66eb8 100644 --- a/main.cpp +++ b/main.cpp @@ -20,6 +20,8 @@ #include "point_light.hpp" #include "tracer.hpp" #include "path_tracer.hpp" +#include "brdf.hpp" +#include "phong_brdf.hpp" using namespace std; using namespace glm; diff --git a/output.png b/output.png index b524a6e..390a4be 100644 Binary files a/output.png and b/output.png differ diff --git a/path_tracer.cpp b/path_tracer.cpp index bb00803..e4d76d5 100644 --- a/path_tracer.cpp +++ b/path_tracer.cpp @@ -53,8 +53,8 @@ vec3 PathTracer::trace_ray(Ray & r, vector
& v_figures, vectordiffuse(n, r, t, _f->m_mat) : vec3(0.0f); - dir_spec_color += vis ? v_lights[l]->specular(n, r, t, _f->m_mat) : vec3(0.0f); + dir_diff_color += vis ? v_lights[l]->diffuse(n, r, i_pos, _f->m_mat) : vec3(0.0f); + dir_spec_color += vis ? v_lights[l]->specular(n, r, i_pos, _f->m_mat) : vec3(0.0f); } // Calculate indirect lighting contribution. diff --git a/phong_brdf.cpp b/phong_brdf.cpp new file mode 100644 index 0000000..a64678e --- /dev/null +++ b/phong_brdf.cpp @@ -0,0 +1,19 @@ +#include "glm/glm.hpp" + +#include "phong_brdf.hpp" + +using glm::reflect; +using glm::pow; +using glm::max; +using glm::dot; + +vec3 PhongBRDF::diffuse(vec3 light_dir, vec3 surface_normal, Ray & incident_ray, vec3 light_diff_color) const { + float n_dot_l = max(dot(surface_normal, light_dir), 0.0f); + return light_diff_color * n_dot_l; +} + +vec3 PhongBRDF::specular(vec3 light_dir, vec3 surface_normal, Ray & incident_ray, vec3 light_spec_color, float shininess) const { + vec3 ref = reflect(light_dir, surface_normal); + float r_dot_l = pow(max(dot(ref, incident_ray.m_direction), 0.0f), shininess); + return light_spec_color * r_dot_l; +} diff --git a/phong_brdf.hpp b/phong_brdf.hpp new file mode 100644 index 0000000..fc8cbe9 --- /dev/null +++ b/phong_brdf.hpp @@ -0,0 +1,16 @@ +#pragma once +#ifndef PHONG_BRDF_HPP +#define PHONG_BRDF_HPP + +#include "brdf.hpp" + +class PhongBRDF: public BRDF{ +public: + PhongBRDF() { } + virtual ~PhongBRDF() { } + + virtual vec3 diffuse(vec3 light_dir, vec3 surface_normal, Ray & incident_ray, vec3 light_diff_color) const; + virtual vec3 specular(vec3 light_dir, vec3 surface_normal, Ray & incident_ray, vec3 light_spec_color, float shininess) const; +}; + +#endif diff --git a/point_light.cpp b/point_light.cpp index 4c23dc6..9aaa305 100644 --- a/point_light.cpp +++ b/point_light.cpp @@ -19,35 +19,26 @@ inline float PointLight::distance(vec3 point) { return length(m_position - point); } -vec3 PointLight::diffuse(vec3 normal, Ray & r, float t, Material & m) const { - float d, att, n_dot_l; - vec3 color, i_pos, l_dir, ref; +vec3 PointLight::diffuse(vec3 normal, Ray & r, vec3 i_pos, Material & m) const { + float d, att; + vec3 l_dir, ref; - i_pos = r.m_origin + t * r.m_direction; l_dir = m_position - i_pos; d = length(l_dir); l_dir = normalize(l_dir); att = 1.0f / (m_const_att + (m_lin_att * d) + (m_quad_att * (d * d))); - n_dot_l = max(dot(normal, l_dir), 0.0f); - color += att * m_diffuse * n_dot_l; - - return color; + return att * m_brdf->diffuse(l_dir, normal, r, m_diffuse); } -vec3 PointLight::specular(vec3 normal, Ray & r, float t, Material & m) const { - float d, att, r_dot_l; - vec3 color, i_pos, l_dir, ref; +vec3 PointLight::specular(vec3 normal, Ray & r, vec3 i_pos, Material & m) const { + float d, att; + vec3 l_dir, ref; - i_pos = r.m_origin + t * r.m_direction; l_dir = m_position - i_pos; d = length(l_dir); l_dir = normalize(l_dir); att = 1.0f / (m_const_att + (m_lin_att * d) + (m_quad_att * (d * d))); - ref = reflect(l_dir, normal); - r_dot_l = pow(max(dot(ref, r.m_direction), 0.0f), m.m_shininess); - color += att * m.m_specular * m_specular * r_dot_l; - - return color; + return att * m.m_specular * m_brdf->specular(l_dir, normal, r, m_specular, m.m_shininess); } diff --git a/point_light.hpp b/point_light.hpp index 7603254..93de77a 100644 --- a/point_light.hpp +++ b/point_light.hpp @@ -10,22 +10,14 @@ public: float m_lin_att; float m_quad_att; - PointLight(): m_const_att(1.0f), m_lin_att(0.0f), m_quad_att(0.0f) { - m_position = vec3(0.0f); - m_diffuse = vec3(1.0f); - m_specular = vec3(1.0f); - } + PointLight(): Light(), m_const_att(1.0f), m_lin_att(0.0f), m_quad_att(0.0f) { } - PointLight(vec3 _p, vec3 _d, vec3 _s, float _c, float _l, float _q): m_const_att(_c), m_lin_att(_l), m_quad_att(_q) { - m_position = _p; - m_diffuse = _d; - m_specular = _s; - } + PointLight(BRDF * _brdf, vec3 _p, vec3 _d, vec3 _s, float _c, float _l, float _q): Light(_brdf, _p, _d, _s), m_const_att(_c), m_lin_att(_l), m_quad_att(_q) { } virtual vec3 direction(vec3 point); virtual float distance(vec3 point); - virtual vec3 diffuse(vec3 normal, Ray & r, float t, Material & m) const; - virtual vec3 specular(vec3 normal, Ray & r, float t, Material & m) const; + 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; }; #endif diff --git a/whitted_tracer.cpp b/whitted_tracer.cpp index 6e01248..8fbaf05 100644 --- a/whitted_tracer.cpp +++ b/whitted_tracer.cpp @@ -51,8 +51,8 @@ vec3 WhittedTracer::trace_ray(Ray & r, vector
& v_figures, vectordiffuse(n, r, t, _f->m_mat) : vec3(0.0f); - dir_spec_color += vis ? v_lights[l]->specular(n, r, t, _f->m_mat) : vec3(0.0f); + dir_diff_color += vis ? v_lights[l]->diffuse(n, r, i_pos, _f->m_mat) : vec3(0.0f); + dir_spec_color += vis ? v_lights[l]->specular(n, r, i_pos, _f->m_mat) : vec3(0.0f); } color += (dir_diff_color * (_f->m_mat.m_diffuse / pi())) + dir_spec_color;