From 7ee6da0234b7c72a646ac752828721c7d958b722 Mon Sep 17 00:00:00 2001 From: Robert Garrett Date: Tue, 6 Jun 2023 18:06:59 -0500 Subject: [PATCH] Feat: Total internal reflection, Schlick's approx. Completion of Chapter 10: Dielectrics. --- src/main.rs | 13 +++++++++++-- src/material.rs | 19 +++++++++++++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 6a590a9..4fee26d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -34,9 +34,9 @@ fn main() { // world let mat_ground = Material::Lambertian{ albedo: Vec3::new(0.8, 0.8, 0.0) }; - let mat_center = Material::Dielectric { index_refraction: 1.5 }; + let mat_center = Material::Lambertian{ albedo: Vec3::new(0.1, 0.2, 0.5) }; let mat_left = Material::Dielectric { index_refraction: 1.5 }; - let mat_right = Material::Metal{ albedo: Vec3::new(0.8, 0.6, 0.2), fuzz: 1.0 }; + let mat_right = Material::Metal{ albedo: Vec3::new(0.8, 0.6, 0.2), fuzz: 0.0 }; let mut world = HittableList::new(); world.add( @@ -68,6 +68,15 @@ fn main() { ) ); + world.add( + Box::new( + Sphere{ + center: Vec3::new(-1.0, 0.0, -1.0), + radius: -0.4, + material: Some(mat_left), } + ) + ); + world.add( Box::new( Sphere{ diff --git a/src/material.rs b/src/material.rs index 8f21757..df1abb3 100644 --- a/src/material.rs +++ b/src/material.rs @@ -4,6 +4,7 @@ use crate::hittable::HitRecord; use crate::vec3; use crate::vec3::Vec3; +use rand::Rng; use rand::rngs::SmallRng; use rand::distributions::Uniform; @@ -64,14 +65,28 @@ impl Material { let refraction_ratio = if rec.front_face { 1.0 / index_refraction } else { *index_refraction }; let unit_direction = Vec3::as_unit(ray_in.dir); - let refracted = Vec3::refract(unit_direction, rec.normal, refraction_ratio); + let cos_theta = vec3::min(Vec3::dot(-unit_direction, rec.normal), 1.0); + let sin_theta = (1.0 - cos_theta * cos_theta).sqrt(); + let cannot_refract = refraction_ratio * sin_theta > 1.0; + let direction = if cannot_refract || Material::reflectance(cos_theta, refraction_ratio) > srng.sample(distrib) { + Vec3::reflect(unit_direction, rec.normal) + } else { + Vec3::refract(unit_direction, rec.normal, refraction_ratio) + }; *scattered = Ray { orig: rec.p, - dir: refracted + dir: direction }; return true; }, } } + + fn reflectance(cosine: f32, ref_idx: f32) -> f32 { + // Schlick's approximation for reflectance. + let r0 = (1.0 - ref_idx) / (1.0 + ref_idx); + let r0 = r0 * r0; + return r0 + (1.0 - r0) * (1.0 - cosine).powf(5.0); + } }