diff --git a/Makefile b/Makefile index be7c947..60a70e6 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ TARGET = ray -HEADERS = ray.hpp figure.hpp sphere.hpp plane.hpp disk.hpp material.hpp light.hpp tracer.hpp -OBJECTS = main.o sphere.o plane.o disk.o tracer.o +HEADERS = ray.hpp figure.hpp sphere.hpp plane.hpp disk.hpp material.hpp light.hpp directional_light.hpp tracer.hpp +OBJECTS = main.o sphere.o plane.o disk.o directional_light.o tracer.o CXX = g++ CXXFLAGS = -ansi -pedantic -Wall -g -DGLM_FORCE_RADIANS -fopenmp LDLIBS = -lm @@ -21,6 +21,8 @@ disk.o: disk.cpp $(HEADERS) tracer.o: tracer.cpp $(HEADERS) +directional_light.o: directional_light.cpp $(HEADERS) + .PHONY: clean clean: $(RM) $(TARGET) $(OBJECTS) diff --git a/directional_light.cpp b/directional_light.cpp new file mode 100644 index 0000000..1c379d7 --- /dev/null +++ b/directional_light.cpp @@ -0,0 +1,26 @@ +#include + +#include +#include + +#include "directional_light.hpp" + +using glm::pi; +using glm::reflect; +using glm::dot; + +vec3 DirectionalLight::shade(vec3 normal, Ray & r, Material & m) const { + float n_dot_l, r_dot_l; + vec3 color, ref; + + //color = m.m_ambient * m_ambient; + + n_dot_l = max(dot(normal, m_position), 0.0); + color += (m.m_diffuse / pi()) * m_diffuse * n_dot_l; + + 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; +} diff --git a/directional_light.hpp b/directional_light.hpp new file mode 100644 index 0000000..477b9e6 --- /dev/null +++ b/directional_light.hpp @@ -0,0 +1,26 @@ +#pragma once +#ifndef DIRECTIONAL_LIGHT_HPP +#define DIRECTIONAL_LIGHT_HPP + +#include "light.hpp" + +class DirectionalLight: public Light { +public: + DirectionalLight() { + m_position = vec3(0.0f); + m_diffuse = vec3(1.0f); + m_specular = vec3(1.0f); + m_ambient = vec3(0.05f); + } + + DirectionalLight(vec3 _p, vec3 _d, vec3 _s, vec3 _a) { + m_position = _p; + m_diffuse = _d; + m_specular = _s; + m_ambient = _a; + } + + virtual vec3 shade(vec3 normal, Ray & r, Material & m) const; +}; + +#endif diff --git a/disk.hpp b/disk.hpp index 127bb9a..feb01d7 100644 --- a/disk.hpp +++ b/disk.hpp @@ -14,19 +14,16 @@ public: float m_radius; Disk(): m_radius(1.0f) { - rho = 0.0f; m_point = vec3(0.0f); m_normal = vec3(0.0f, 1.0f, 0.0f); } Disk(float x, float y, float z, float nx, float ny, float nz, float _r): m_radius(_r) { - rho = 0.0f; m_point = vec3(x, y, z); m_normal = normalize(vec3(nx, ny, nz)); } Disk(vec3 _p, vec3 _n, float _r): m_radius(_r) { - rho = 0.0f; m_point = _p; m_normal = normalize(_n); } diff --git a/figure.hpp b/figure.hpp index a7d2b1e..23f7f66 100644 --- a/figure.hpp +++ b/figure.hpp @@ -11,23 +11,12 @@ using glm::vec3; class Figure { public: - vec3 color; Material m_mat; - float rho; virtual ~Figure() { } virtual bool intersect(Ray & r, float & t) const = 0; - virtual vec3 normal_at_int(Ray & r, float & t) const = 0; - - virtual void set_color(float r, float g, float b) { - color = vec3(r, g, b); - } - - virtual void set_color(vec3 rgb) { - color = vec3(rgb); - } }; #endif diff --git a/light.hpp b/light.hpp index 3ee2560..d9077b2 100644 --- a/light.hpp +++ b/light.hpp @@ -4,6 +4,9 @@ #include +#include "ray.hpp" +#include "material.hpp" + using glm::vec3; class Light { @@ -13,8 +16,13 @@ public: vec3 m_specular; vec3 m_ambient; - Light(): m_position(vec3(0.0f)), m_diffuse(vec3(1.0f)), m_specular(vec3(1.0f)), m_ambient(vec3(0.05f)) { } - Light(vec3 _p, vec3 _d, vec3 _s, vec3 _a): m_position(_p), m_diffuse(_d), m_specular(_s), m_ambient(_a) { } + float max(float a, float b) const { + return a >= b ? a : b; + } + + virtual ~Light() { } + + virtual vec3 shade(vec3 normal, Ray & r, Material & m) const = 0; }; #endif diff --git a/main.cpp b/main.cpp index 991bbac..aff96fb 100644 --- a/main.cpp +++ b/main.cpp @@ -14,6 +14,7 @@ #include "plane.hpp" #include "disk.hpp" #include "light.hpp" +#include "directional_light.hpp" #include "tracer.hpp" using namespace std; @@ -147,105 +148,106 @@ static void scene_1(vector
& vf, vector & vl) { Sphere * s; Plane * p; Disk * d; - Light * l; + DirectionalLight * l; s = new Sphere(1.0f, 1.0f, -2.0f, 0.5f); - s->set_color(1.0f, 0.0f, 0.0f); + s->m_mat.m_diffuse = vec3(1.0f, 0.0f, 0.0f); vf.push_back(static_cast
(s)); s = new Sphere(-1.0f, 1.0f, -2.0f, 0.5f); - s->set_color(0.0f, 1.0f, 0.0f); + s->m_mat.m_diffuse = vec3(0.0f, 1.0f, 0.0f); vf.push_back(static_cast
(s)); s = new Sphere(1.0f, -1.0f, -2.0f, 0.5f); - s->set_color(0.0f, 0.0f, 1.0f); + s->m_mat.m_diffuse = vec3(0.0f, 0.0f, 1.0f); vf.push_back(static_cast
(s)); s = new Sphere(-1.0f, -1.0f, -2.0f, 0.5f); - s->set_color(1.0f, 0.0f, 1.0f); + s->m_mat.m_diffuse = vec3(1.0f, 0.0f, 1.0f); vf.push_back(static_cast
(s)); s = new Sphere(0.0f, 0.0f, -2.0f, 1.0f); - s->set_color(1.0f, 1.0f, 0.0f); + //s->set_color(1.0f, 1.0f, 0.0f); + s->m_mat.m_diffuse = vec3(1.0f, 1.0f, 0.0f); vf.push_back(static_cast
(s)); p = new Plane(vec3(0.0f, -1.5f, 0.0f), vec3(0.0f, 1.0f, 0.0f)); - p->set_color(1.0f, 0.5f, 0.4f); + p->m_mat.m_diffuse = vec3(1.0f, 0.5f, 0.4f); vf.push_back(static_cast
(p)); s = new Sphere(-1.5f, 0.0f, -2.0f, 0.5f); - s->set_color(1.0f, 1.0f, 1.0f); - s->rho = 0.3f; + s->m_mat.m_diffuse = vec3(1.0f, 1.0f, 1.0f); + s->m_mat.m_rho = 0.3f; vf.push_back(static_cast
(s)); s = new Sphere(1.5f, 0.0f, -2.0f, 0.5f); - s->set_color(1.0f, 1.0f, 1.0f); - s->rho = 0.08f; + s->m_mat.m_diffuse = vec3(1.0f, 1.0f, 1.0f); + s->m_mat.m_rho = 0.08f; vf.push_back(static_cast
(s)); s = new Sphere(0.0f, 1.5f, -2.0f, 0.5f); - s->set_color(1.0f, 1.0f, 1.0f); - s->rho = 0.5f; + s->m_mat.m_diffuse = vec3(1.0f, 1.0f, 1.0f); + s->m_mat.m_rho = 0.5f; vf.push_back(static_cast
(s)); s = new Sphere(0.0f, 0.0f, -1.0f, 0.25f); - s->set_color(1.0f, 1.0f, 1.0f); - s->rho = 0.1f; + s->m_mat.m_diffuse = vec3(1.0f, 1.0f, 1.0f); + s->m_mat.m_rho = 0.1f; vf.push_back(static_cast
(s)); d = new Disk(vec3(0.0f, 2.0f, -2.0f), vec3(0.0f, -1.0f, 0.0f), 1.0f); - d->set_color(1.0f, 1.0f, 0.0f); - d->rho = 0.8f; + d->m_mat.m_diffuse = vec3(1.0f, 1.0f, 0.0f); + d->m_mat.m_rho = 0.8f; vf.push_back(static_cast
(d)); - l = new Light(); + l = new DirectionalLight(); l->m_position = normalize(vec3(1.0f, 1.0f, 1.0f)); l->m_diffuse = vec3(0.0f, 1.0f, 1.0f); - vl.push_back(l); + vl.push_back(static_cast(l)); - l = new Light(); + l = new DirectionalLight(); l->m_position = normalize(vec3(-1.0f, 1.0f, 1.0f)); l->m_diffuse = vec3(1.0f, 1.0f, 0.0f); - vl.push_back(l); + vl.push_back(static_cast(l)); - l = new Light(); + l = new DirectionalLight(); l->m_position = normalize(vec3(0.0f, 1.0f, -1.0f)); l->m_diffuse = vec3(1.0f, 0.0f, 1.0f); - vl.push_back(l); + vl.push_back(static_cast(l)); } static void scene_2(vector
& vf, vector & vl) { Sphere * s; Plane * p; - Light * l; + DirectionalLight * l; p = new Plane(vec3(0.0f, -1.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f)); - p->set_color(0.0f, 1.0f, 0.0f); + //p->set_color(0.0f, 1.0f, 0.0f); vf.push_back(static_cast
(p)); p = new Plane(vec3(-1.0f, 0.0f, 0.0f), vec3(1.0f, 0.0f, 0.0f)); - p->set_color(1.0f, 0.0f, 0.0f); + //p->set_color(1.0f, 0.0f, 0.0f); vf.push_back(static_cast
(p)); p = new Plane(vec3(1.0f, 0.0f, 0.0f), vec3(-1.0f, 0.0f, 0.0f)); - p->set_color(0.0f, 0.0f, 1.0f); + //p->set_color(0.0f, 0.0f, 1.0f); vf.push_back(static_cast
(p)); p = new Plane(vec3(0.0f, 1.0f, 0.0f), vec3(0.0f, -1.0f, 0.0f)); - p->set_color(1.0f, 1.0f, 1.0f); + //p->set_color(1.0f, 1.0f, 1.0f); vf.push_back(static_cast
(p)); p = new Plane(vec3(0.0f, 0.0f, -2.0f), vec3(0.0f, 0.0f, 1.0f)); - p->set_color(1.0f, 0.0f, 1.0f); + //p->set_color(1.0f, 0.0f, 1.0f); vf.push_back(static_cast
(p)); s = new Sphere(-0.4f, -0.5f, -1.5f, 0.5f); - s->set_color(1.0f, 1.0f, 0.0f); - s->rho = 0.4f; + //s->set_color(1.0f, 1.0f, 0.0f); + //s->rho = 0.4f; vf.push_back(static_cast
(s)); - l = new Light(); + l = new DirectionalLight(); l->m_position = normalize(vec3(0.0f, 0.0f, 1.0f)); l->m_diffuse = vec3(1.0f, 1.0f, 1.0f); - vl.push_back(l); + vl.push_back(static_cast(l)); } diff --git a/material.hpp b/material.hpp index 811967e..afa2240 100644 --- a/material.hpp +++ b/material.hpp @@ -13,8 +13,18 @@ public: vec3 m_ambient; float m_rho; float m_shininess; + float m_ref_index; - Material(): m_diffuse(vec3(1.0f)), m_specular(vec3(1.0f)), m_ambient(vec3(1.0f)), m_rho(0.0f), m_shininess(89.0f) { } + Material(): m_diffuse(vec3(1.0f)), m_specular(vec3(1.0f)), m_ambient(vec3(1.0f)), m_rho(0.0f), m_shininess(89.0f), m_ref_index(1.0f) { } + + Material(const Material & m) { + m_diffuse = m.m_diffuse; + m_specular = m.m_specular; + m_ambient = m.m_ambient; + m_rho = m.m_rho; + m_shininess = m.m_shininess; + m_ref_index = m.m_ref_index; + } }; #endif diff --git a/output.ppm b/output.ppm index 20116e3..e45ff7b 100644 Binary files a/output.ppm and b/output.ppm differ diff --git a/plane.hpp b/plane.hpp index da2f650..5ac3baa 100644 --- a/plane.hpp +++ b/plane.hpp @@ -14,17 +14,11 @@ public: vec3 m_point; vec3 m_normal; - Plane(): m_point(vec3(0.0f)), m_normal(0.0f, 0.0f, 1.0f) { - rho = 0.0f; - } + Plane(): m_point(vec3(0.0f)), m_normal(0.0f, 0.0f, 1.0f) { } - Plane(float x, float y, float z, float nx, float ny, float nz): m_point(vec3(x, y, z)), m_normal(normalize(vec3(nx, ny, nz))) { - rho = 0.0f; - } + Plane(float x, float y, float z, float nx, float ny, float nz): m_point(vec3(x, y, z)), m_normal(normalize(vec3(nx, ny, nz))) { } - Plane(vec3 _p, vec3 _n): m_point(_p), m_normal(normalize(_n)) { - rho = 0.0f; - } + Plane(vec3 _p, vec3 _n): m_point(_p), m_normal(normalize(_n)) { } virtual ~Plane() { } diff --git a/sphere.hpp b/sphere.hpp index 46ec952..63092ea 100644 --- a/sphere.hpp +++ b/sphere.hpp @@ -13,13 +13,9 @@ public: vec3 m_center; float m_radius; - Sphere(): m_center(vec3(0.0f)), m_radius(0.5f) { - rho = 0.0f; - } + Sphere(): m_center(vec3(0.0f)), m_radius(0.5f) { } - Sphere(float x, float y, float z, float r): m_center(vec3(x, y, z)), m_radius(r) { - rho = 0.0f; - } + Sphere(float x, float y, float z, float r): m_center(vec3(x, y, z)), m_radius(r) { } Sphere(vec3 _c, float r): m_center(_c), m_radius(r) { } diff --git a/tracer.cpp b/tracer.cpp index af96680..cf3889e 100644 --- a/tracer.cpp +++ b/tracer.cpp @@ -1,14 +1,10 @@ -#include #include #include -#include #include #include "tracer.hpp" -#define PI 3.14159265358979f -#define SHININESS 89.0f #define MAX_RECURSION 9 #define BIAS 0.000001f @@ -20,23 +16,14 @@ using glm::radians; using glm::dot; using glm::reflect; using glm::clamp; +using glm::tan; static const vec3 BCKG_COLOR = vec3(0.16f, 0.66f, 0.72f); -static inline float max(float a, float b) { - return a >= b ? a : b; -} - static inline float random01() { return static_cast(rand()) / static_cast(RAND_MAX); } -Tracer::Tracer(): m_h(480), m_w(640), m_fov(90.0f), m_a_ratio(640.0f / 480.0f) {} - -Tracer::Tracer(int h, int w, float fov): m_h(h), m_w(w), m_fov(fov) { - m_a_ratio = static_cast(w) / static_cast(h); -} - vec2 Tracer::sample_pixel(int i, int j) const { float pxNDC; float pyNDC; @@ -51,9 +38,8 @@ vec2 Tracer::sample_pixel(int i, int j) const { return vec2(pxS, pyS); } -vec3 Tracer::trace_ray(Ray & r, vector
& vf, vector & vl, unsigned int rec_level) const { - size_t f_index; - float t, _t, n_dot_l; +vec3 Tracer::trace_ray(Ray & r, vector
& v_figures, vector & v_lights, unsigned int rec_level) const { + float t, _t; Figure * _f; vec3 n, color, i_pos, ref; Ray sr, rr; @@ -62,11 +48,10 @@ vec3 Tracer::trace_ray(Ray & r, vector
& vf, vector & vl, uns t = numeric_limits::max(); _f = NULL; - for (size_t f = 0; f < vf.size(); f++) { - if (vf[f]->intersect(r, _t) && _t < t) { + for (size_t f = 0; f < v_figures.size(); f++) { + if (v_figures[f]->intersect(r, _t) && _t < t) { t = _t; - _f = vf[f]; - f_index = f; + _f = v_figures[f]; } } @@ -74,33 +59,29 @@ vec3 Tracer::trace_ray(Ray & r, vector
& vf, vector & vl, uns i_pos = r.m_origin + (t * r.m_direction); n = _f->normal_at_int(r, t); - if (_f->rho > 0.0f && rec_level < MAX_RECURSION) { - rr = Ray(reflect(r.m_direction, n), i_pos + n * BIAS); - color = _f->rho * trace_ray(rr, vf, vl, rec_level + 1); - } else if (rec_level >= MAX_RECURSION) - return vec3(BCKG_COLOR); - - for (size_t l = 0; l < vl.size(); l++) { + for (size_t l = 0; l < v_lights.size(); l++) { vis = true; - sr = Ray(vl[l]->m_position, i_pos + n * BIAS); + sr = Ray(v_lights[l]->m_position, i_pos + n * BIAS); - for (size_t f = 0; f < vf.size(); f++) { - if (vf[f]->intersect(sr, _t)) { + for (size_t f = 0; f < v_figures.size(); f++) { + if (v_figures[f]->intersect(sr, _t)) { vis = false; break; } } - color += 0.08f * BCKG_COLOR; - - n_dot_l = max(dot(n, vl[l]->m_position), 0.0); - color += (vis ? 1.0f : 0.0f) * (_f->color / PI) * vl[l]->m_diffuse * n_dot_l; - - ref = reflect(vl[l]->m_position, n); - color += (vis ? 1.0f : 0.0f) * vl[l]->m_specular * pow(max(dot(ref, r.m_direction), 0.0f), SHININESS); + color += (vis ? 1.0f : 0.0f) * v_lights[l]->shade(n, r, _f->m_mat); } + if (_f->m_mat.m_rho > 0.0f && rec_level < MAX_RECURSION) { + rr = Ray(reflect(r.m_direction, n), i_pos + n * BIAS); + color += _f->m_mat.m_rho * trace_ray(rr, v_figures, v_lights, rec_level + 1); + + } else if (rec_level >= MAX_RECURSION) + return vec3(BCKG_COLOR); + return clamp(color, 0.0f, 1.0f); + } else return vec3(BCKG_COLOR); } diff --git a/tracer.hpp b/tracer.hpp index 6eeaa32..cb77cc5 100644 --- a/tracer.hpp +++ b/tracer.hpp @@ -21,12 +21,14 @@ public: float m_fov; float m_a_ratio; - Tracer(); + Tracer(): m_h(480), m_w(640), m_fov(90.0f), m_a_ratio(640.0f / 480.0f) { } - Tracer(int h, int w, float fov); + Tracer(int h, int w, float fov): m_h(h), m_w(w), m_fov(fov) { + m_a_ratio = static_cast(w) / static_cast(h); + }; vec2 sample_pixel(int i, int j) const; - vec3 trace_ray(Ray & r, vector
& f, vector & l, unsigned int rec_level) const; + vec3 trace_ray(Ray & r, vector
& v_figures, vector & v_lights, unsigned int rec_level) const; }; #endif