#include "material.h" #include bool Lambertian::scatter(const Ray& r_in, const hit_record& rec, Color& attenuation, Ray& scattered) const { //Vec3 scatter_direction = rec.normal + random_in_unit_sphere(); Vec3 scatter_direction = rec.normal + random_unit_vector(); //Vec3 scatter_direction = random_in_hemisphere(rec.normal); scattered = Ray(rec.p, scatter_direction, r_in.time()); attenuation = albedo->value(rec.u, rec.v, rec.p); return true; } bool Metal::scatter(const Ray& r_in, const hit_record& rec, Color& attenuation, Ray& scattered) const { Vec3 reflected = reflect(unit_vector(r_in.direction()), rec.normal); scattered = Ray(rec.p, reflected + fuzz * random_in_unit_sphere(), r_in.time()); attenuation = albedo; return (dot(scattered.direction(), rec.normal) > 0); } double schlick(double cosine, double ref_idx) { auto r0 = (1 - ref_idx) / (1 + ref_idx); r0 = r0 * r0; return r0 + (1 - r0) * std::pow((1 - cosine), 5); } bool Dielectric::scatter(const Ray& r_in, const hit_record& rec, Color& attenuation, Ray& scattered) const { attenuation = Color(1.0, 1.0, 1.0); double etai_over_etat = rec.front_face ? 1.0 / ref_idx : ref_idx; Vec3 unit_direction = unit_vector(r_in.direction()); double cos_theta = std::fmin(dot(-unit_direction, rec.normal), 1.0); double sin_theta = std::sqrt(1.0 - cos_theta*cos_theta); double reflect_prob = schlick(cos_theta, etai_over_etat); if (etai_over_etat * sin_theta > 1.0 || random_double() < reflect_prob) { Vec3 reflected = reflect(unit_direction, rec.normal); scattered = Ray(rec.p, reflected, r_in.time()); return true; } Vec3 refracted = refract(unit_direction, rec.normal, etai_over_etat); scattered = Ray(rec.p, refracted, r_in.time()); return true; }