diff --git a/.clang_complete b/.clang_complete new file mode 100644 index 0000000..ff5d913 --- /dev/null +++ b/.clang_complete @@ -0,0 +1,5 @@ +-ansi +-pedantic +-Wall +-DGLM_FORCE_RADIANS +-fopenmp \ No newline at end of file diff --git a/directional_light.hpp b/directional_light.hpp index dd79080..6fca10c 100644 --- a/directional_light.hpp +++ b/directional_light.hpp @@ -8,11 +8,11 @@ using glm::normalize; -class DirectionalLight: public Light { +class DirectionalLight: public InfinitesimalLight { public: - DirectionalLight(): Light() { } + DirectionalLight(): InfinitesimalLight() { } - DirectionalLight(vec3 _p, vec3 _d, vec3 _s): Light(normalize(_p), _d, _s) { } + DirectionalLight(vec3 _p, vec3 _d, vec3 _s): InfinitesimalLight(normalize(_p), _d, _s) { } virtual vec3 direction(vec3 point); virtual float distance(vec3 point); diff --git a/light.hpp b/light.hpp index 16c42a3..d0d360b 100644 --- a/light.hpp +++ b/light.hpp @@ -11,6 +11,8 @@ using glm::vec3; class Light { public: + typedef enum LIGHT_TYPE { INFINITESIMAL = 0, AREA } ltype_t; + vec3 m_position; vec3 m_diffuse; vec3 m_specular; @@ -21,6 +23,45 @@ public: virtual ~Light() { } + virtual ltype_t light_type() { + return type; + } + + virtual vec3 direction(vec3 point) = 0; + virtual float distance(vec3 point) = 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; + +protected: + ltype_t type; +}; + +class InfinitesimalLight: public Light { +public: + InfinitesimalLight(): Light() { + type = INFINITESIMAL; + } + + InfinitesimalLight(vec3 _p, vec3 _d, vec3 _s): Light(_p, _d, _s) { + type = INFINITESIMAL; + } + + virtual vec3 direction(vec3 point) = 0; + virtual float distance(vec3 point) = 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; +}; + +class AreaLight: public Light { +public: + AreaLight(): Light() { + type = AREA; + } + + AreaLight(vec3 _p, vec3 _d, vec3 _s): Light(_p, _d, _s) { + type = AREA; + } + virtual vec3 direction(vec3 point) = 0; virtual float distance(vec3 point) = 0; virtual vec3 diffuse(vec3 normal, Ray & r, vec3 i_pos, Material & m) const = 0; diff --git a/output.png b/output.png index d2a5cb7..e495701 100644 Binary files a/output.png and b/output.png differ diff --git a/path_tracer.cpp b/path_tracer.cpp index ad232ca..ca7fb37 100644 --- a/path_tracer.cpp +++ b/path_tracer.cpp @@ -34,7 +34,7 @@ vec3 PathTracer::trace_ray(Ray & r, Scene * s, unsigned int rec_level) const { // Take the intersection point and the normal of the surface at that point. i_pos = r.m_origin + (t * r.m_direction); n = _f->normal_at_int(r, t); - + // Check if the material is not reflective/refractive. if (!_f->m_mat->m_refract) { // Calculate the direct lighting. @@ -42,13 +42,18 @@ vec3 PathTracer::trace_ray(Ray & r, Scene * s, unsigned int rec_level) const { // For every light source vis = true; - // Cast a shadow ray to determine visibility. - sr = Ray(s->m_lights[l]->direction(i_pos), i_pos + n * BIAS); - for (size_t f = 0; f < s->m_figures.size(); f++) { - if (s->m_figures[f]->intersect(sr, _t) && _t < s->m_lights[l]->distance(i_pos)) { - vis = false; - break; + if (s->m_lights[l]->light_type() == Light::INFINITESIMAL) { + // Cast a shadow ray to determine visibility. + sr = Ray(s->m_lights[l]->direction(i_pos), i_pos + n * BIAS); + for (size_t f = 0; f < s->m_figures.size(); f++) { + if (s->m_figures[f]->intersect(sr, _t) && _t < s->m_lights[l]->distance(i_pos)) { + vis = false; + break; + } } + } else if (s->m_lights[l]->light_type() == Light::AREA) { + // Area lights not supported with Whitted ray tracing. + vis = false; } // Evaluate the shading model accounting for visibility. diff --git a/point_light.hpp b/point_light.hpp index 3685a5c..55bc2e6 100644 --- a/point_light.hpp +++ b/point_light.hpp @@ -4,15 +4,15 @@ #include "light.hpp" -class PointLight: public Light { +class PointLight: public InfinitesimalLight { public: float m_const_att; float m_lin_att; float m_quad_att; - PointLight(): Light(), m_const_att(1.0f), m_lin_att(0.0f), m_quad_att(0.0f) { } + PointLight(): InfinitesimalLight(), 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): Light(_p, _d, _s), m_const_att(_c), m_lin_att(_l), m_quad_att(_q) { } + PointLight(vec3 _p, vec3 _d, vec3 _s, float _c, float _l, float _q): InfinitesimalLight(_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); diff --git a/whitted_tracer.cpp b/whitted_tracer.cpp index 2c96b2e..afa5ba2 100644 --- a/whitted_tracer.cpp +++ b/whitted_tracer.cpp @@ -36,18 +36,24 @@ vec3 WhittedTracer::trace_ray(Ray & r, Scene * s, unsigned int rec_level) const // Check if the material is not reflective/refractive. if (!_f->m_mat->m_refract) { + // Calculate the direct lighting. for (size_t l = 0; l < s->m_lights.size(); l++) { // For every light source vis = true; - // Cast a shadow ray to determine visibility. - sr = Ray(s->m_lights[l]->direction(i_pos), i_pos + n * BIAS); - for (size_t f = 0; f < s->m_figures.size(); f++) { - if (s->m_figures[f]->intersect(sr, _t) && _t < s->m_lights[l]->distance(i_pos)) { - vis = false; - break; + if (s->m_lights[l]->light_type() == Light::INFINITESIMAL) { + // Cast a shadow ray to determine visibility. + sr = Ray(s->m_lights[l]->direction(i_pos), i_pos + n * BIAS); + for (size_t f = 0; f < s->m_figures.size(); f++) { + if (s->m_figures[f]->intersect(sr, _t) && _t < s->m_lights[l]->distance(i_pos)) { + vis = false; + break; + } } + } else if (s->m_lights[l]->light_type() == Light::AREA) { + // Area lights not supported with Whitted ray tracing. + vis = false; } // Evaluate the shading model accounting for visibility.