Feat: Rudimentary dielectric... but broken
Dielectric material matching Raytracing in a Weekend book chapter 10.2. But it isn't right. The spheres turn into solid black holes. As I'm making the commit, I've found the problem. I'm separating it out so I can tag it and explore the code a bit more. See the step-by-step changes, and such.
This commit is contained in:
@@ -34,8 +34,8 @@ 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::Lambertian{ albedo: Vec3::new(0.7, 0.3, 0.3) };
|
let mat_center = Material::Dielectric { index_refraction: 1.5 };
|
||||||
let mat_left = Material::Metal{ albedo: Vec3::new(0.8, 0.8, 0.8), fuzz: 0.3 };
|
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: 1.0 };
|
||||||
|
|
||||||
let mut world = HittableList::new();
|
let mut world = HittableList::new();
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ use rand::distributions::Uniform;
|
|||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum Material{
|
pub enum Material{
|
||||||
Lambertian{ albedo: Vec3 },
|
Lambertian { albedo: Vec3 },
|
||||||
Metal{ albedo:Vec3, fuzz: f32 },
|
Metal { albedo:Vec3, fuzz: f32 },
|
||||||
|
Dielectric { index_refraction: f32 },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Material {
|
impl Material {
|
||||||
@@ -58,6 +59,19 @@ impl Material {
|
|||||||
*attenuation = *albedo;
|
*attenuation = *albedo;
|
||||||
return Vec3::dot(scattered.dir, rec.normal) > 0.0;
|
return Vec3::dot(scattered.dir, rec.normal) > 0.0;
|
||||||
},
|
},
|
||||||
|
Material::Dielectric { index_refraction } => {
|
||||||
|
*attenuation = Vec3::ones();
|
||||||
|
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);
|
||||||
|
|
||||||
|
*scattered = Ray {
|
||||||
|
orig: rec.p,
|
||||||
|
dir: refracted
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
41
src/vec3.rs
41
src/vec3.rs
@@ -87,23 +87,30 @@ impl Vec3{
|
|||||||
let g = (self.y * scale).sqrt();
|
let g = (self.y * scale).sqrt();
|
||||||
let b = (self.z * scale).sqrt();
|
let b = (self.z * scale).sqrt();
|
||||||
|
|
||||||
let ir = (Vec3::clamp(r, 0.0, 0.999) * 256.0) as i32;
|
let ir = (clamp(r, 0.0, 0.999) * 256.0) as i32;
|
||||||
let ig = (Vec3::clamp(g, 0.0, 0.999) * 256.0) as i32;
|
let ig = (clamp(g, 0.0, 0.999) * 256.0) as i32;
|
||||||
let ib = (Vec3::clamp(b, 0.0, 0.999) * 256.0) as i32;
|
let ib = (clamp(b, 0.0, 0.999) * 256.0) as i32;
|
||||||
format!("{} {} {}", ir, ig, ib)
|
format!("{} {} {}", ir, ig, ib)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn near_zero(&self) -> bool {
|
pub fn near_zero(&self) -> bool {
|
||||||
let epsilon: f32 = 1e-8;
|
let epsilon: f32 = 1e-4;
|
||||||
return
|
return
|
||||||
self.x < epsilon &&
|
self.x.abs() < epsilon &&
|
||||||
self.y < epsilon &&
|
self.y.abs() < epsilon &&
|
||||||
self.z < epsilon
|
self.z.abs() < epsilon
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reflect(v: Vec3, n: Vec3) -> Vec3 {
|
pub fn reflect(v: Vec3, n: Vec3) -> Vec3 {
|
||||||
return v - n * Vec3::dot(v, n) * 2.0;
|
return v - n * Vec3::dot(v, n) * 2.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn refract(uv: Vec3, n: Vec3, etai_over_etat: f32) -> Vec3 {
|
||||||
|
let cos_theta = min(Vec3::dot(-uv, n), 1.0);
|
||||||
|
let r_out_perp = (uv + n * cos_theta) * etai_over_etat;
|
||||||
|
let r_out_parallel = n * -(1.0 - r_out_perp.length_squared()).abs().sqrt();
|
||||||
|
r_out_perp + r_out_parallel
|
||||||
|
}
|
||||||
|
|
||||||
pub fn dot(left: Vec3, right: Vec3) -> f32{
|
pub fn dot(left: Vec3, right: Vec3) -> f32{
|
||||||
left.x * right.x +
|
left.x * right.x +
|
||||||
@@ -124,15 +131,6 @@ impl Vec3{
|
|||||||
*v / len
|
*v / len
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clamp(input: f32, min: f32, max: f32) -> f32 {
|
|
||||||
if input < min {
|
|
||||||
return min;
|
|
||||||
} else if input > max {
|
|
||||||
return max;
|
|
||||||
} else {
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
impl Add for Vec3 {
|
impl Add for Vec3 {
|
||||||
type Output = Vec3;
|
type Output = Vec3;
|
||||||
@@ -281,6 +279,17 @@ impl Display for Vec3 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clamp(input: f32, lower: f32, upper: f32) -> f32 {
|
||||||
|
min(max(input, lower), upper)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn min(a: f32, b: f32) -> f32 {
|
||||||
|
if a < b { a } else { b }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn max(a: f32, b: f32) -> f32 {
|
||||||
|
if a > b { a } else { b }
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test{
|
mod test{
|
||||||
|
|||||||
Reference in New Issue
Block a user