ft: 10: metals

This commit is contained in:
2026-04-16 14:04:55 +02:00
parent e8f84b590b
commit b756cc394a
12 changed files with 199 additions and 41 deletions

View File

@@ -1,14 +1,26 @@
use crate::{objects::traits::Hittable, ray::Ray, vec3::Vec3};
use std::sync::Arc;
use crate::{
objects::{materials::traits::Material, traits::Hittable},
ray::Ray,
vec3::Vec3,
};
pub struct Hit {
t: f32,
p: Vec3,
n: Vec3,
mat: Arc<dyn Material>,
}
impl Hit {
pub fn new(t: f32, p: Vec3, n: Vec3) -> Hit {
Hit { t: t, p: p, n: n }
pub fn new(t: f32, p: Vec3, n: Vec3, mat: Arc<dyn Material>) -> Self {
Self {
t: t,
p: p,
n: n,
mat: mat,
}
}
pub fn t(&self) -> &f32 {
@@ -23,6 +35,10 @@ impl Hit {
&self.n
}
pub fn mat(&self) -> Arc<dyn Material> {
self.mat.clone()
}
pub fn hit_list<T: Hittable>(hittables: &Vec<T>, r: &Ray) -> Option<Hit> {
let mut closest: Option<Hit> = None;
for hittable in hittables {

2
src/objects/materials.rs Normal file
View File

@@ -0,0 +1,2 @@
pub mod lambertian;
pub mod traits;

View File

@@ -0,0 +1,79 @@
use rand::RngExt;
use crate::{
objects::{hit::Hit, materials::traits::Material},
ray::Ray,
vec3::{Colour, Vec3},
};
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;
}
}
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;
}
}

View File

@@ -0,0 +1,5 @@
use crate::{objects::hit::Hit, ray::Ray, vec3::Colour};
pub trait Material {
fn scatter(&self, hit: &Hit, ray: &Ray) -> Option<(Ray, Colour)>;
}

View File

@@ -1,19 +1,31 @@
use core::f32::math::sqrt;
use std::sync::Arc;
use crate::objects::hit::Hit;
use crate::objects::materials::traits::Material;
use crate::objects::traits::Hittable;
use crate::Vec3;
pub struct Sphere {
center: Vec3,
radius: f32,
material: Arc<dyn Material>,
}
impl Sphere {
pub fn new(center: Vec3, radius: f32) -> Sphere {
Sphere {
pub fn new(center: Vec3, r: f32, mat: Arc<dyn Material>) -> Self {
Self {
center: center,
radius: radius,
radius: r,
material: mat,
}
}
pub fn xyz(x: f32, y: f32, z: f32, r: f32, mat: Arc<dyn Material>) -> Self {
Self {
center: Vec3::new(x, y, z),
radius: r,
material: mat,
}
}
}
@@ -31,7 +43,7 @@ impl Hittable for Sphere {
} else {
let t = (h - sqrt(d)) / a;
let p = r.at(t);
Some(Hit::new(t, p, self.normal_at(&p)))
Some(Hit::new(t, p, self.normal_at(&p), self.material.clone()))
}
}