diff --git a/directional_light.cpp b/directional_light.cpp index 1c379d7..90edc3f 100644 --- a/directional_light.cpp +++ b/directional_light.cpp @@ -13,8 +13,6 @@ 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; diff --git a/directional_light.hpp b/directional_light.hpp index 477b9e6..730d85b 100644 --- a/directional_light.hpp +++ b/directional_light.hpp @@ -10,14 +10,12 @@ public: 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) { + DirectionalLight(vec3 _p, vec3 _d, vec3 _s) { m_position = _p; m_diffuse = _d; m_specular = _s; - m_ambient = _a; } virtual vec3 shade(vec3 normal, Ray & r, Material & m) const; diff --git a/main.cpp b/main.cpp index aff96fb..6e6230a 100644 --- a/main.cpp +++ b/main.cpp @@ -31,6 +31,7 @@ static vec3 ** image; static void scene_1(vector
& vf, vector & vl); static void scene_2(vector
& vf, vector & vl); +static void scene_3(vector
& vf, vector & vl); int main(int argc, char ** argv) { FILE * out; @@ -90,7 +91,7 @@ int main(int argc, char ** argv) { image[i] = new vec3[g_w]; } - scene_1(figures, lights); + scene_3(figures, lights); tracer = Tracer(g_h, g_w, g_fov); @@ -167,7 +168,6 @@ static void scene_1(vector
& vf, vector & vl) { 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->m_mat.m_diffuse = vec3(1.0f, 1.0f, 0.0f); vf.push_back(static_cast
(s)); @@ -183,6 +183,8 @@ static void scene_1(vector
& vf, vector & vl) { s = new Sphere(1.5f, 0.0f, -2.0f, 0.5f); s->m_mat.m_diffuse = vec3(1.0f, 1.0f, 1.0f); s->m_mat.m_rho = 0.08f; + s->m_mat.m_refract = true; + s->m_mat.m_ref_index = 1.1f; vf.push_back(static_cast
(s)); s = new Sphere(0.0f, 1.5f, -2.0f, 0.5f); @@ -195,9 +197,11 @@ static void scene_1(vector
& vf, vector & vl) { 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->m_mat.m_diffuse = vec3(1.0f, 1.0f, 0.0f); - d->m_mat.m_rho = 0.8f; + d = new Disk(vec3(-0.0f, -0.0f, -0.5f), vec3(0.0f, 0.0f, 0.1f), 0.25f); + d->m_mat.m_diffuse = vec3(1.0f, 0.0f, 0.0f); + d->m_mat.m_rho = 0.3f; + d->m_mat.m_refract = true; + d->m_mat.m_ref_index = 1.33f; vf.push_back(static_cast
(d)); l = new DirectionalLight(); @@ -222,28 +226,28 @@ static void scene_2(vector
& vf, vector & vl) { 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->m_mat.m_diffuse = vec3(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->m_mat.m_diffuse = vec3(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->m_mat.m_diffuse = vec3(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->m_mat.m_diffuse = vec3(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->m_mat.m_diffuse = vec3(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->m_mat.m_diffuse = vec3(1.0f, 1.0f, 0.0f); + s->m_mat.m_rho = 0.4f; vf.push_back(static_cast
(s)); l = new DirectionalLight(); @@ -251,3 +255,35 @@ static void scene_2(vector
& vf, vector & vl) { l->m_diffuse = vec3(1.0f, 1.0f, 1.0f); vl.push_back(static_cast(l)); } + +static void scene_3(vector
& vf, vector & vl) { + Sphere * s; + Plane * p; + DirectionalLight * l; + + s = new Sphere(0.0f, -0.15f, -2.0f, 1.0f); + s->m_mat.m_diffuse = vec3(1.0f, 0.5f, 0.0f); + s->m_mat.m_rho = 0.4f; + s->m_mat.m_refract = true; + s->m_mat.m_ref_index = 1.33f; + vf.push_back(static_cast
(s)); + + s = new Sphere(2.0f, 0.0f, -2.0f, 1.0f); + s->m_mat.m_diffuse = vec3(1.0f, 0.0f, 1.0f); + s->m_mat.m_rho = 0.6f; + vf.push_back(static_cast
(s)); + + s = new Sphere(-1.0f, 0.25f, -3.25f, 1.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->m_mat.m_diffuse = vec3(1.0f, 1.0f, 1.0f); + p->m_mat.m_specular = vec3(0.0f); + vf.push_back(static_cast
(p)); + + l = new DirectionalLight(); + l->m_position = normalize(vec3(-1.0f, 1.0f, 1.0f)); + l->m_diffuse = vec3(1.0f, 1.0f, 1.0f); + vl.push_back(static_cast(l)); +} diff --git a/material.hpp b/material.hpp index afa2240..3bfd242 100644 --- a/material.hpp +++ b/material.hpp @@ -10,20 +10,20 @@ class Material { public: vec3 m_diffuse; vec3 m_specular; - vec3 m_ambient; float m_rho; float m_shininess; float m_ref_index; + bool m_refract; - 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(): m_diffuse(vec3(1.0f)), m_specular(vec3(1.0f)), m_rho(0.0f), m_shininess(89.0f), m_ref_index(1.0f), m_refract(false) { } 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; + m_refract = m.m_refract; } }; diff --git a/output.ppm b/output.ppm index e45ff7b..d16815a 100644 Binary files a/output.ppm and b/output.ppm differ diff --git a/ray.hpp b/ray.hpp index 8826c1c..162b889 100644 --- a/ray.hpp +++ b/ray.hpp @@ -10,10 +10,13 @@ class Ray { public: vec3 m_direction; vec3 m_origin; + float m_ref_index; - Ray(): m_direction(vec3(0.0f, 0.0f, -1.0f)), m_origin(vec3(0.0f)) { } - Ray(float dx, float dy, float dz, float ox, float oy, float oz): m_direction(vec3(dx, dy, dz)), m_origin(vec3(ox, oy, oz)) {} - Ray(vec3 _d, vec3 _o): m_direction(_d), m_origin(_o) { } + Ray(): m_direction(vec3(0.0f, 0.0f, -1.0f)), m_origin(vec3(0.0f)), m_ref_index(1.0f) { } + Ray(float dx, float dy, float dz, float ox, float oy, float oz, float _r = 1.0f): m_direction(vec3(dx, dy, dz)), + m_origin(vec3(ox, oy, oz)), + m_ref_index(_r) { } + Ray(vec3 _d, vec3 _o, float _r = 1.0f): m_direction(_d), m_origin(_o), m_ref_index(_r) { } }; #endif diff --git a/tracer.cpp b/tracer.cpp index cf3889e..41404ce 100644 --- a/tracer.cpp +++ b/tracer.cpp @@ -1,8 +1,7 @@ +#include #include #include -#include - #include "tracer.hpp" #define MAX_RECURSION 9 @@ -15,8 +14,10 @@ using glm::normalize; using glm::radians; using glm::dot; using glm::reflect; +using glm::refract; using glm::clamp; using glm::tan; +using glm::cos; static const vec3 BCKG_COLOR = vec3(0.16f, 0.66f, 0.72f); @@ -24,16 +25,30 @@ static inline float random01() { return static_cast(rand()) / static_cast(RAND_MAX); } +static float fresnel(const vec3 & i, const vec3 & n, const float ir1, const float ir2) { + float cos_t1 = dot(i, n); + float cos_t2 = dot(normalize(refract(i, n, ir1 / ir2)), n); + float sin_t2 = (ir1 / ir2) * sqrt(1.0f - (cos_t2 * cos_t2)); + + if (sin_t2 >= 1.0f) + return 1.0f; + + float fr_par = ((ir2 * cos_t1) - (ir1 * cos_t2)) / ((ir2 * cos_t1) + (ir1 * cos_t2)); + float fr_per = ((ir1 * cos_t2) - (ir2 * cos_t1)) / ((ir1 * cos_t2) + (ir2 * cos_t1)); + + return ((fr_par * fr_par) + (fr_per * fr_per)) / 2.0f; +} + vec2 Tracer::sample_pixel(int i, int j) const { float pxNDC; float pyNDC; float pxS; float pyS; pyNDC = (static_cast(i) + random01()) / m_h; - pyS = (1.0f - (2.0f * pyNDC)) * tan(radians(m_fov) / 2); + pyS = (1.0f - (2.0f * pyNDC)) * tan(radians(m_fov / 2)); pxNDC = (static_cast(j) + random01()) / m_w; pxS = (2.0f * pxNDC) - 1.0f; - pxS *= m_a_ratio * tan(radians(m_fov) / 2); + pxS *= m_a_ratio * tan(radians(m_fov / 2)); return vec2(pxS, pyS); } @@ -44,6 +59,7 @@ vec3 Tracer::trace_ray(Ray & r, vector
& v_figures, vector & vec3 n, color, i_pos, ref; Ray sr, rr; bool vis; + float kr; t = numeric_limits::max(); _f = NULL; @@ -73,9 +89,21 @@ vec3 Tracer::trace_ray(Ray & r, vector
& v_figures, vector & 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); + if (_f->m_mat.m_refract) + kr = fresnel(r.m_direction, n, r.m_ref_index, _f->m_mat.m_ref_index); + else + kr = _f->m_mat.m_rho; + + if (kr > 0.0f && rec_level < MAX_RECURSION) { + rr = Ray(normalize(reflect(r.m_direction, n)), i_pos + n * BIAS); + color += _f->m_mat.m_rho * kr * trace_ray(rr, v_figures, v_lights, rec_level + 1); + + } else if (rec_level >= MAX_RECURSION) + return vec3(BCKG_COLOR); + + if (_f->m_mat.m_refract && kr < 1.0f && rec_level < MAX_RECURSION) { + rr = Ray(normalize(refract(r.m_direction, n, r.m_ref_index / _f->m_mat.m_ref_index)), i_pos - n * BIAS, _f->m_mat.m_ref_index); + color += (1.0f - _f->m_mat.m_rho) * (1.0f - kr) * trace_ray(rr, v_figures, v_lights, rec_level + 1); } else if (rec_level >= MAX_RECURSION) return vec3(BCKG_COLOR);