63 lines
1.4 KiB
Rust
63 lines
1.4 KiB
Rust
|
use super::{
|
||
|
Ray,
|
||
|
HitRecord,
|
||
|
Color,
|
||
|
Vec3,
|
||
|
};
|
||
|
|
||
|
pub struct Lambertian {
|
||
|
albedo: Color,
|
||
|
}
|
||
|
|
||
|
pub struct Metal {
|
||
|
albedo: Color,
|
||
|
}
|
||
|
|
||
|
pub trait Material: Sync + Send {
|
||
|
fn scatter(&self,r_in: &Ray, rec: &HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool;
|
||
|
}
|
||
|
|
||
|
impl Lambertian {
|
||
|
pub fn new(a: &Color) -> Self {
|
||
|
Lambertian {
|
||
|
albedo: a.clone(),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Material for Lambertian {
|
||
|
fn scatter(&self, _r_in: &Ray, rec: &HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool {
|
||
|
let mut scatter_direction = rec.normal + Vec3::random_unit_vector();
|
||
|
|
||
|
if scatter_direction.near_zero() {
|
||
|
scatter_direction = rec.normal;
|
||
|
}
|
||
|
|
||
|
*scattered = Ray::new(rec.p, scatter_direction);
|
||
|
*attenuation = self.albedo.clone();
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Metal {
|
||
|
pub fn new(a: &Color) -> Self {
|
||
|
Metal {
|
||
|
albedo: *a,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn clone(&self) -> Self {
|
||
|
Self::new(&self.albedo.clone())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Material for Metal {
|
||
|
fn scatter(&self, r_in: &Ray, rec: &HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool {
|
||
|
let reflected = Vec3::reflect(&Vec3::unit_vector(r_in.direction()), &rec.normal);
|
||
|
|
||
|
*scattered = Ray::new(rec.p, reflected);
|
||
|
*attenuation = self.albedo.clone();
|
||
|
|
||
|
return Vec3::dot(scattered.direction(), rec.normal) > 0.0;
|
||
|
}
|
||
|
}
|