From 79e6d04e504d70542684999dc035907e523f9de6 Mon Sep 17 00:00:00 2001 From: djairoh Date: Tue, 21 Apr 2026 23:03:46 +0200 Subject: [PATCH] ft: 11: dielectrics --- src/main.rs | 6 +++++- src/objects/materials/dielectric.rs | 31 ++++++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 56ba16e..908463e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,18 +21,22 @@ fn main() { pretty_env_logger::init(); // setup objects + let blue = Arc::new(Metal::rgb(0.2, 0.4, 0.8, 1., 0.1)); let metal = Arc::new(Metal::rgb(0.7, 0.4, 0.2, 1., 0.1)); let ground = Arc::new(Lambertian::rgb(0.8, 0.8, 0., 1.0)); let center = Arc::new(Lambertian::rgb(0.1, 0.2, 0.5, 1.)); let left = Arc::new(Dielectric::new(1.5)); + let bubble = Arc::new(Dielectric::new(1. / 1.5)); let right = Arc::new(Metal::rgb(0.8, 0.6, 0.2, 1., 1.0)); let mut world = vec![Sphere::xyz(0., 0.5, -0.8, 0.1, metal.clone())]; world.push(Sphere::xyz(0., -100.5, -1., 100., ground.clone())); world.push(Sphere::xyz(0., 0., -1.2, 0.5, center.clone())); world.push(Sphere::xyz(-1., 0., -1.0, 0.5, left.clone())); + world.push(Sphere::xyz(-1., 0., -1.0, 0.4, bubble.clone())); world.push(Sphere::xyz(1., 0., -1.0, 0.5, right.clone())); + world.push(Sphere::xyz(0., 0.7, -0.4, 0.2, blue.clone())); - let c = Camera::new(16. / 9., 800, 2, 50); + let c = Camera::new(16. / 9., 1920, 3, 50); c.render(&world); } diff --git a/src/objects/materials/dielectric.rs b/src/objects/materials/dielectric.rs index 441b252..dfb8fd1 100644 --- a/src/objects/materials/dielectric.rs +++ b/src/objects/materials/dielectric.rs @@ -1,7 +1,11 @@ +use core::f32::math::sqrt; + +use rand::RngExt; + use crate::{ objects::{hit::Hit, materials::traits::Material}, ray::Ray, - vec3::Colour, + vec3::{Colour, Vec3}, }; pub struct Dielectric { @@ -14,6 +18,13 @@ impl Dielectric { refraction_index: refraction_index, } } + + fn _reflectance(cos: f32, refraction_index: f32) -> f32 { + // Shlick's approximation + let mut r0 = (1. - refraction_index) / (1. + refraction_index); + r0 *= r0; + return r0 + (1. - r0) * (1. - cos).powf(5.); + } } impl Material for Dielectric { @@ -24,7 +35,21 @@ impl Material for Dielectric { self.refraction_index }; let unit = ray.dir().get_unit(); - let refr = unit.refract(hit.n(), ri); - Some((Ray::new(*hit.p(), refr), Colour::new(1., 1., 1.))) + let cos_theta = if -unit.dot(hit.n()) > 1. { + 1. + } else { + -unit.dot(hit.n()) + }; + let sin_theta = sqrt(1. - cos_theta * cos_theta); + let cannot_refract = ri * sin_theta > 1.; + + let dir: Vec3; + let mut rng = rand::rng(); + if cannot_refract || Dielectric::_reflectance(cos_theta, ri) > rng.random::() { + dir = unit.reflect(hit.n()); + } else { + dir = unit.refract(hit.n(), ri); + } + Some((Ray::new(*hit.p(), dir), Colour::new(1., 1., 1.))) } }