diff options
| author | Sakarias Johansson <sakarias.johansson@goodbyekansas.com> | 2023-01-16 20:58:55 +0100 |
|---|---|---|
| committer | Sakarias Johansson <sakarias.johansson@goodbyekansas.com> | 2023-01-16 20:58:55 +0100 |
| commit | 03e5a88f9b7da79749370685e8f5afaf03a25b4a (patch) | |
| tree | 9e0fd5e12bcd9739f5292864c9da9084a0030489 /racer-tracer/src/material/dialectric.rs | |
| parent | 3167ec992f1f81b2252a2db3642fff943c4f14bf (diff) | |
| download | racer-tracer-03e5a88f9b7da79749370685e8f5afaf03a25b4a.tar.gz racer-tracer-03e5a88f9b7da79749370685e8f5afaf03a25b4a.tar.xz racer-tracer-03e5a88f9b7da79749370685e8f5afaf03a25b4a.zip | |
🎨 Add dialectric material
Diffstat (limited to 'racer-tracer/src/material/dialectric.rs')
| -rw-r--r-- | racer-tracer/src/material/dialectric.rs | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/racer-tracer/src/material/dialectric.rs b/racer-tracer/src/material/dialectric.rs new file mode 100644 index 0000000..5f3aa02 --- /dev/null +++ b/racer-tracer/src/material/dialectric.rs @@ -0,0 +1,53 @@ +use crate::{ + material::Material, + ray::Ray, + util::random_double, + vec3::{dot, reflect, refract, Color}, +}; + +pub struct Dialectric { + refraction_index: f64, +} + +impl Dialectric { + pub fn new(refraction_index: f64) -> Self { + Self { refraction_index } + } + + fn reflectance(cosine: f64, refraction_index: f64) -> f64 { + // Schlick approximation + let mut r0 = (1.0 - refraction_index) / (1.0 + refraction_index); + r0 = r0 * r0; + r0 + (1.0 - r0) * (1.0 - cosine).powf(5.0) + } +} + +impl Material for Dialectric { + fn scatter( + &self, + ray: &crate::ray::Ray, + rec: &crate::geometry::HitRecord, + ) -> Option<(Ray, Color)> { + let refraction_ratio = if rec.front_face { + 1.0 / self.refraction_index + } else { + self.refraction_index + }; + + let unit_direction = &ray.direction().unit_vector(); + let cos_theta = f64::min(dot(&-unit_direction, &rec.normal), 1.0); + let sin_theta = f64::sqrt(1.0 - cos_theta * cos_theta); + + let cannot_refract = refraction_ratio * sin_theta > 1.0; + + let direction = if cannot_refract + || Dialectric::reflectance(cos_theta, refraction_ratio) > random_double() + { + reflect(unit_direction, &rec.normal) + } else { + refract(unit_direction, &rec.normal, refraction_ratio) + }; + + Some((Ray::new(rec.point, direction), Color::new(1.0, 1.0, 1.0))) + } +} |
