diff --git a/src/main.cpp b/src/main.cpp index 32355f9..c0b2e20 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -39,7 +39,7 @@ colour ray_colour(const ray& r, const hittable& world, int depth) auto t = 0.5 * (unit_direction.y() + 1.0); auto a = colour(0.5, 0.6, 0.7); - auto b = colour(1.0, 1.0, 1.0); + auto b = colour(0.5, 0.5, 0.5); return lerp(a, b, t); } @@ -53,7 +53,7 @@ int main() world.add(make_shared( point3(0,0,-1), 0.5, - make_shared(colour(0.7,0.3,0.3)))); + make_shared(colour(0.1,0.2,0.5)))); world.add(make_shared( point3(0,-100.5,-1), 100, @@ -62,11 +62,15 @@ int main() world.add(make_shared( point3(1,0,-1), 0.5, - make_shared(colour(0.8,0.6,0.2)))); + make_shared(colour(0.8,0.6,0.2), 0.0))); world.add(make_shared( point3(-1,0,-1), 0.5, - make_shared(colour(0.8,0.8,0.8)))); + make_shared(1.5))); + world.add(make_shared( + point3(-1,0,-1), + -0.45, + make_shared(1.5))); camera cam; diff --git a/src/material.h b/src/material.h index cd79906..895b06b 100644 --- a/src/material.h +++ b/src/material.h @@ -13,6 +13,13 @@ class material ray& scattered) const = 0; }; +double schlick(double cosine, double refraction_index) +{ + auto r0 = (1-refraction_index) / (1+refraction_index); + r0 = r0*r0; + return r0 + (1-r0)*pow(1-cosine, 5); +} + class lambertian : public material { public: @@ -37,7 +44,9 @@ class lambertian : public material class metal : public material { public: - metal(const colour& a) : albedo_(a) {} + metal(const colour& a, double f) : + albedo_(a), + fuzz_(f < 1 ? f : 1) {} virtual bool scatter( const ray& r_in, @@ -46,11 +55,55 @@ class metal : public material ray& scattered) const { vec3 reflected = reflect(unit_vector(r_in.direction()), rec.normal); - scattered = ray(rec.p, reflected); + scattered = ray(rec.p, reflected + fuzz_*random_in_unit_sphere()); attenuation = albedo_; return dot(scattered.direction(), rec.normal) > 0; } private: colour albedo_; + double fuzz_; +}; + +class dielectric : public material +{ + public: + dielectric(double ri) : refraction_index_(ri) {} + + virtual bool scatter( + const ray& r_in, + const hit_record& rec, + colour& attenuation, + ray& scattered) const + { + attenuation = colour(1.0,1.0,1.0); + double etai_over_etat = rec.front_face ? (1.0 / refraction_index_) : refraction_index_; + + vec3 unit_direction = unit_vector(r_in.direction()); + + double cos_theta = fmin(dot(-unit_direction, rec.normal), 1.0); + double sin_theta = sqrt(1.0 - cos_theta*cos_theta); + if (etai_over_etat * sin_theta > 1.0) + { + vec3 reflected = reflect(unit_direction, rec.normal); + scattered = ray(rec.p, reflected); + return true; + } + + double reflect_prob = schlick(cos_theta, etai_over_etat); + if (random_double() < reflect_prob) + { + vec3 reflected = reflect(unit_direction, rec.normal); + scattered = ray(rec.p, reflected); + return true; + } + + vec3 refracted = refract(unit_direction, rec.normal, etai_over_etat); + scattered = ray(rec.p, refracted); + + return true; + } + + private: + double refraction_index_; }; diff --git a/src/vec3.h b/src/vec3.h index ff09f68..c47ff8f 100755 --- a/src/vec3.h +++ b/src/vec3.h @@ -164,3 +164,12 @@ vec3 reflect(const vec3& v, const vec3& n) { return v - 2*dot(v,n)*n; } + +vec3 refract(const vec3& uv, const vec3& n, double etai_over_etat) +{ + auto cos_theta = dot(-uv, n); + vec3 r_out_parallel = etai_over_etat * (uv + cos_theta*n); + vec3 r_out_perp = -sqrt(1.0 - r_out_parallel.length_squared()) * n; + + return r_out_parallel + r_out_perp; +}