diff --git a/src/main.rs b/src/main.rs index 7451276..ec839ca 100644 --- a/src/main.rs +++ b/src/main.rs @@ -30,8 +30,10 @@ fn ray_color(r: &Ray, world: &mut dyn Hittable, depth: i32) -> Color { } if world.hit(r, 0.001, INFINITY, &mut rec) { - let target = rec.p + random_in_hemisphere(&rec.normal); - return 0.5 * ray_color(&Ray::new(rec.p, target - rec.p), world, depth - 1) + let mut scattered = Ray::new_empty(); + let mut attenuation = Color::new_empty(); + + if rec.mat_ptr } let unit_direction: Vec3 = r.direction().unit_vector(); diff --git a/src/material.rs b/src/material.rs index 778e813..f5029c8 100644 --- a/src/material.rs +++ b/src/material.rs @@ -1,12 +1,12 @@ use crate::hittable::HitRecord; -use crate::ray::{Ray, self}; -use crate::vec3::{Color, random_unit_vector}; +use crate::ray::Ray; +use crate::vec3::{Color, random_unit_vector, reflect}; -pub struct Material { +pub struct Material { } -trait Scatter { +pub trait Scatter: { fn scatter(&self, r_in: &Ray, rec: HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool; } @@ -23,8 +23,33 @@ impl Lambertian { impl Scatter for Lambertian { fn scatter(&self, r_in: &Ray, rec: HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool { let scatter_direction = rec.normal + random_unit_vector(); + + if scatter_direction.near_zero() { + scatter_direction = rec.normal; + } + scattered = &mut Ray::new(rec.p, scatter_direction); attenuation = &mut self.albedo; return true; } +} + +pub struct Metal { + pub albedo: Color +} + +impl Metal { + pub fn new(a: &Color) -> Self { + Metal { albedo: *a } + } +} + +impl Scatter for Metal { + fn scatter(&self, r_in: &Ray, rec: HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool { + let reflected = reflect(&r_in.direction(), &rec.normal); + scattered = &mut Ray::new(rec.p, rec.normal); + attenuation = &mut self.albedo; + + scattered.direction().dot(&rec.normal) > 0.0 + } } \ No newline at end of file diff --git a/src/ray.rs b/src/ray.rs index 20bcb89..44687b7 100644 --- a/src/ray.rs +++ b/src/ray.rs @@ -11,6 +11,10 @@ impl Ray { Ray { origin, direction } } + pub fn new_empty() -> Self { + Ray { direction: Point3::new_empty(), origin: Vec3::new_empty() } + } + pub fn origin(&self) -> Point3 { self.origin } diff --git a/src/vec3.rs b/src/vec3.rs index 94e6278..6b13893 100644 --- a/src/vec3.rs +++ b/src/vec3.rs @@ -12,6 +12,10 @@ impl Vec3 { Vec3 { elements: [x, y, z] } } + pub fn new_empty() -> Self { + Vec3::new(0.0, 0.0, 0.0) + } + pub fn x(&self) -> f64 { self.elements[0] } @@ -59,6 +63,11 @@ impl Vec3 { pub fn random_range(min: f64, max: f64) -> Self { Vec3::new(random_range_f64(min, max), random_range_f64(min, max), random_range_f64(min, max)) } + + pub fn near_zero(&self) -> bool { + let s = 1e-8; + (self.x().abs() < s) && (self.y().abs() < s) && (self.z().abs() < s) + } } impl Add for Vec3 { @@ -212,4 +221,8 @@ pub fn random_in_hemisphere(normal: &Vec3) -> Vec3 { } else { return -in_unit_sphere; } +} + +pub fn reflect(v: &Vec3, n: &Vec3) -> Vec3 { + *v - 2.0 * v.dot(n) * *n } \ No newline at end of file