83 lines
1.9 KiB
Rust
83 lines
1.9 KiB
Rust
use rand::RngExt;
|
|
use serde::Deserialize;
|
|
|
|
use crate::{
|
|
objects::{hit::Hit, materials::traits::Material},
|
|
ray::Ray,
|
|
vec3::{Colour, Vec3},
|
|
};
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct Lambertian {
|
|
albedo: Colour,
|
|
prob: f32,
|
|
}
|
|
|
|
impl Lambertian {
|
|
pub fn new(albedo: Colour, prob: f32) -> Self {
|
|
Self {
|
|
albedo: albedo,
|
|
prob: prob,
|
|
}
|
|
}
|
|
|
|
pub fn rgb(r: f32, g: f32, b: f32, prob: f32) -> Self {
|
|
Self {
|
|
albedo: Colour::new(r, g, b),
|
|
prob: prob,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Material for Lambertian {
|
|
fn scatter(&self, hit: &Hit, ray: &Ray) -> Option<(Ray, Colour)> {
|
|
let mut rng = rand::rng();
|
|
if self.prob >= rng.random::<f32>() {
|
|
let mut dir = *hit.n() + Vec3::random_unit();
|
|
if dir.near_zero() {
|
|
dir = *hit.n();
|
|
}
|
|
let scattered = Ray::new(*hit.p(), dir);
|
|
return Some((scattered, self.albedo));
|
|
}
|
|
return None;
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct Metal {
|
|
albedo: Colour,
|
|
prob: f32,
|
|
fuzz: f32,
|
|
}
|
|
|
|
impl Metal {
|
|
pub fn new(albedo: Colour, prob: f32, fuzz: f32) -> Self {
|
|
Self {
|
|
albedo: albedo,
|
|
prob: prob,
|
|
fuzz: fuzz,
|
|
}
|
|
}
|
|
|
|
pub fn rgb(r: f32, g: f32, b: f32, prob: f32, fuzz: f32) -> Self {
|
|
Self {
|
|
albedo: Colour::new(r, g, b),
|
|
prob: prob,
|
|
fuzz: fuzz,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Material for Metal {
|
|
fn scatter(&self, hit: &Hit, ray: &Ray) -> Option<(Ray, Colour)> {
|
|
let mut rng = rand::rng();
|
|
if self.prob >= rng.random::<f32>() {
|
|
let mut refl = ray.dir().reflect(hit.n());
|
|
refl = refl.get_unit() + self.fuzz * Vec3::random_unit();
|
|
return Some((Ray::new(*hit.p(), refl), self.albedo));
|
|
}
|
|
return None;
|
|
}
|
|
}
|