diff --git a/Makefile b/Makefile index 3f71a98..bdedd79 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 phong_brdf.o point_light.o tracer.o path_tracer.o whitted_tracer.o +OBJECTS = main.o disk.o plane.o sphere.o directional_light.o phong_brdf.o point_light.o spot_light.o tracer.o path_tracer.o whitted_tracer.o DEPENDS = $(OBJECTS:.o=.d) CXXFLAGS = -ansi -pedantic -Wall -DGLM_FORCE_RADIANS -fopenmp LDLIBS = -lfreeimage diff --git a/main.cpp b/main.cpp index e6733bd..d2becff 100644 --- a/main.cpp +++ b/main.cpp @@ -19,6 +19,7 @@ #include "light.hpp" #include "directional_light.hpp" #include "point_light.hpp" +#include "spot_light.hpp" #include "tracer.hpp" #include "path_tracer.hpp" #include "whitted_tracer.hpp" @@ -364,7 +365,7 @@ void scene_2(vector
& vf, vector & vl, mat4x4 & i_model_view) Plane * p; Disk * d; PointLight * l; - + s = new Sphere(0.2f, 0.0f, -0.75f, 0.25f); s->m_mat.m_diffuse = vec3(1.0f); s->m_mat.m_rho = 0.2f; diff --git a/output.png b/output.png index 11c9573..357304b 100644 Binary files a/output.png and b/output.png differ diff --git a/spot_light.cpp b/spot_light.cpp new file mode 100644 index 0000000..3e9175b --- /dev/null +++ b/spot_light.cpp @@ -0,0 +1,49 @@ +#include +#include + +#include "spot_light.hpp" + +using glm::pi; +using glm::reflect; +using glm::length; +using glm::normalize; +using glm::dot; +using glm::pow; +using glm::max; +using glm::acos; +using glm::radians; + +vec3 SpotLight::diffuse(vec3 normal, Ray & r, vec3 i_pos, Material & m) const { + float d, att, spot_effect; + vec3 l_dir, ref; + + l_dir = m_position - i_pos; + d = length(l_dir); + l_dir = normalize(l_dir); + spot_effect = dot(m_spot_dir, -l_dir); + + if (acos(spot_effect) < radians(m_spot_cutoff)) { + spot_effect = pow(spot_effect, m_spot_exponent); + att = spot_effect / (m_const_att + (m_lin_att * d) + (m_quad_att * (d * d))); + return att * m.m_brdf->diffuse(l_dir, normal, r, m_diffuse); + + } else + return vec3(0.0f); +} + +vec3 SpotLight::specular(vec3 normal, Ray & r, vec3 i_pos, Material & m) const { + float d, att, spot_effect; + vec3 l_dir, ref; + + l_dir = m_position - i_pos; + d = length(l_dir); + l_dir = normalize(l_dir); + spot_effect = dot(m_spot_dir, -l_dir); + + if (acos(spot_effect) < radians(m_spot_cutoff)) { + spot_effect = pow(spot_effect, m_spot_exponent); + att = spot_effect / (m_const_att + (m_lin_att * d) + (m_quad_att * (d * d))); + return att * m.m_brdf->specular(l_dir, normal, r, m_specular, m.m_shininess); + } else + return vec3(0.0f); +} diff --git a/spot_light.hpp b/spot_light.hpp new file mode 100644 index 0000000..506670c --- /dev/null +++ b/spot_light.hpp @@ -0,0 +1,29 @@ +#pragma once +#ifndef SPOT_LIGHT_HPP +#define SPOT_LIGHT_HPP + +#include + +#include "point_light.hpp" + +using glm::vec3; +using glm::normalize; + +class SpotLight: public PointLight { +public: + float m_spot_cutoff; + float m_spot_exponent; + vec3 m_spot_dir; + + SpotLight(): PointLight(), m_spot_cutoff(45.0f), m_spot_exponent(0.0f), m_spot_dir(vec3(0.0f, -1.0f, 0.0f)) { } + + SpotLight(vec3 _p, vec3 _d, vec3 _s, float _c, float _l, float _q, float _sco, float _se, vec3 _sd): PointLight(_p, _d, _s, _c, _l, _q), + m_spot_cutoff(_sco), + m_spot_exponent(_se), + m_spot_dir(normalize(_sd)) { } + + 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