summaryrefslogtreecommitdiff
path: root/src/material.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/material.rs')
-rw-r--r--src/material.rs37
1 files changed, 32 insertions, 5 deletions
diff --git a/src/material.rs b/src/material.rs
index a654f4d..833ef19 100644
--- a/src/material.rs
+++ b/src/material.rs
@@ -1,3 +1,4 @@
+use rand::Rng;
use crate::calculus::calculus::{Ray, Vec3};
use crate::common::Color;
use crate::object::HitRecord;
@@ -5,7 +6,8 @@ use crate::object::HitRecord;
#[derive(Clone)]
pub enum MaterialType {
Diffuse,
- Metal(f32), // color fuzz
+ Metallic(f32), // fuzz
+ Transparent(f32), // refraction index
}
#[derive(Clone)]
@@ -17,9 +19,9 @@ pub struct Material {
impl Material {
pub fn new(albedo: Color, material_type: MaterialType) -> Self {
let mut material_type = material_type;
- if let MaterialType::Metal(fuzz) = material_type {
+ if let MaterialType::Metallic(fuzz) = material_type {
let fuzz = if fuzz < 1.0 { fuzz } else { fuzz };
- material_type = MaterialType::Metal(fuzz);
+ material_type = MaterialType::Metallic(fuzz);
}
Self { albedo, material_type }
}
@@ -34,11 +36,30 @@ impl Material {
scatter_direction
}
}
- MaterialType::Metal(fuzz) => {
+ MaterialType::Metallic(fuzz) => {
let mut reflected = r_in.reflect(&rec.normal);
- reflected.unit().add(&Vec3::random_unit().scalar_mul(fuzz))
+ reflected.add(&Vec3::random_unit().scalar_mul(fuzz))
}
+ MaterialType::Transparent(refraction_index) => {
+ let ri = if rec.front_face {
+ 1.0 / refraction_index
+ } else {
+ refraction_index
+ };
+ let cos_theta = f32::min(
+ r_in.direction.unit().scalar_mul(-1.0).dot_prod(&rec.normal),
+ 1.0
+ );
+ let sin_theta = (1.0 - cos_theta * cos_theta).sqrt();
+ let cannot_refract = ri * sin_theta > 1.0;
+ let random: f32 = rand::rng().random();
+ if cannot_refract || Self::reflectance(cos_theta, ri) > random {
+ r_in.direction.unit().reflect(&rec.normal)
+ } else {
+ r_in.refract(&rec.normal, ri)
+ }
+ }
};
scattered.origin = rec.position;
attenuation.r = self.albedo.r;
@@ -46,4 +67,10 @@ impl Material {
attenuation.b = self.albedo.b;
true
}
+
+ fn reflectance(cosine: f32, refraction_index: f32) -> f32 {
+ let mut r0 = (1.0 - refraction_index) / (1.0 + refraction_index);
+ r0 = r0 * r0;
+ r0 + (1.0 - r0) * (1.0 - cosine).powi(5)
+ }
} \ No newline at end of file