From 0a0080ce803f5781096d6368ede14a3694f7a935 Mon Sep 17 00:00:00 2001 From: Armin Friedl Date: Sat, 30 Jul 2022 18:58:41 +0200 Subject: [PATCH] Schlick reflection --- rtiww/src/material.h | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/rtiww/src/material.h b/rtiww/src/material.h index e026201..20537de 100644 --- a/rtiww/src/material.h +++ b/rtiww/src/material.h @@ -57,27 +57,36 @@ public: virtual bool scatter(const ray &r_in, const hit_record &rec, color &attenuation, ray &scattered) const override { - attenuation = color(1.0, 1.0, 1.0); - double refraction_ratio = rec.front_face ? (1.0/ir) : ir; + attenuation = color(1.0, 1.0, 1.0); + double refraction_ratio = rec.front_face ? (1.0 / ir) : ir; - 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); + 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); - bool cannot_refract = refraction_ratio * sin_theta > 1.0; - vec3 direction; + bool cannot_refract = refraction_ratio * sin_theta > 1.0; + vec3 direction; - if (cannot_refract) - direction = reflect(unit_direction, rec.normal); - else - direction = refract(unit_direction, rec.normal, refraction_ratio); + if (cannot_refract || + reflectance(cos_theta, refraction_ratio) > random_double()) + direction = reflect(unit_direction, rec.normal); + else + direction = refract(unit_direction, rec.normal, refraction_ratio); - scattered = ray(rec.p, direction); - return true; + scattered = ray(rec.p, direction); + return true; } public: double ir; + +private: + static double reflectance(double cosine, double ref_idx) { + // Use Schlick's approximation for reflectance + auto r0 = (1 - ref_idx) / (1 + ref_idx); + r0 = r0 * r0; + return r0 + (1 - r0) * pow((1 - cosine), 5); + } }; #endif // MATERIAL_H_