Feat: Total internal reflection, Schlick's approx.
Completion of Chapter 10: Dielectrics.
This commit is contained in:
13
src/main.rs
13
src/main.rs
@@ -34,9 +34,9 @@ fn main() {
|
|||||||
// world
|
// world
|
||||||
|
|
||||||
let mat_ground = Material::Lambertian{ albedo: Vec3::new(0.8, 0.8, 0.0) };
|
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_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();
|
let mut world = HittableList::new();
|
||||||
world.add(
|
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(
|
world.add(
|
||||||
Box::new(
|
Box::new(
|
||||||
Sphere{
|
Sphere{
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use crate::hittable::HitRecord;
|
|||||||
use crate::vec3;
|
use crate::vec3;
|
||||||
use crate::vec3::Vec3;
|
use crate::vec3::Vec3;
|
||||||
|
|
||||||
|
use rand::Rng;
|
||||||
use rand::rngs::SmallRng;
|
use rand::rngs::SmallRng;
|
||||||
use rand::distributions::Uniform;
|
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 refraction_ratio = if rec.front_face { 1.0 / index_refraction } else { *index_refraction };
|
||||||
|
|
||||||
let unit_direction = Vec3::as_unit(ray_in.dir);
|
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 {
|
*scattered = Ray {
|
||||||
orig: rec.p,
|
orig: rec.p,
|
||||||
dir: refracted
|
dir: direction
|
||||||
};
|
};
|
||||||
return true;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user