summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--material_dielectric.cpp15
-rw-r--r--material_dielectric.h11
2 files changed, 24 insertions, 2 deletions
diff --git a/material_dielectric.cpp b/material_dielectric.cpp
index 3aaf259..ed8e4eb 100644
--- a/material_dielectric.cpp
+++ b/material_dielectric.cpp
@@ -9,13 +9,24 @@ bool material_dielectric::scatter(ray3d &r, const object &hit_obj, double hit_t,
assert(hit_obj.is_on(hit_p));
auto n = hit_obj.normal_vector(hit_p);
auto ri_ = ri_inv;
- if (dot(r.direction(), n) > 0) {
+ auto cos1 = dot(r.direction(), n); // -cos(a1)
+ if (cos1 > 0) {
// the ray is started from the object's inner,
// use normal vector and ri on the surface's inner side
n = -n;
ri_ = 1.0 / ri_;
+ } else {
+ cos1 = -cos1;
+ }
+ vec3d r2;
+ // determine reflection or refraction using Schlick's Approximation.
+ if (reflectance(cos1, ri_) > ruvg.range01_scalar()) {
+ // reflect
+ r2 = n.reflect(r.direction());
+ } else {
+ // refract
+ r2 = n.refract<true>(r.direction(), ri_);
}
- const auto r2 = n.refract<true>(r.direction(), ri_); // refracted vector
r.direction(r2.unit_vec());
r.source(hit_p);
return true;
diff --git a/material_dielectric.h b/material_dielectric.h
index 48382b4..46b17da 100644
--- a/material_dielectric.h
+++ b/material_dielectric.h
@@ -10,8 +10,19 @@
class material_dielectric : public material {
double ri_inv;
+
+ static double reflectance(double cosine, double ref_idx) {
+ assert(cosine > 0);
+ assert(ref_idx > 0);
+ // 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);
+ }
+
public:
explicit material_dielectric(double ri) : ri_inv{1.0 / ri} {}
+
bool scatter(ray3d &r, const object &hit_obj, double hit_t, random_uv_gen_3d &ruvg) const override;
};