ft (wip): 10: dielectrics

This commit is contained in:
2026-04-16 15:38:01 +02:00
parent b756cc394a
commit 1920376e34
6 changed files with 71 additions and 7 deletions

View File

@@ -11,15 +11,17 @@ pub struct Hit {
p: Vec3,
n: Vec3,
mat: Arc<dyn Material>,
front_face: bool,
}
impl Hit {
pub fn new(t: f32, p: Vec3, n: Vec3, mat: Arc<dyn Material>) -> Self {
pub fn new(t: f32, p: Vec3, n: Vec3, mat: Arc<dyn Material>, front_face: bool) -> Self {
Self {
t: t,
p: p,
n: n,
n: if front_face { n } else { -n },
mat: mat,
front_face: front_face,
}
}
@@ -39,6 +41,10 @@ impl Hit {
self.mat.clone()
}
pub fn front_face(&self) -> bool {
self.front_face
}
pub fn hit_list<T: Hittable>(hittables: &Vec<T>, r: &Ray) -> Option<Hit> {
let mut closest: Option<Hit> = None;
for hittable in hittables {

View File

@@ -1,2 +1,3 @@
pub mod dielectric;
pub mod lambertian;
pub mod traits;

View File

@@ -0,0 +1,30 @@
use crate::{
objects::{hit::Hit, materials::traits::Material},
ray::Ray,
vec3::Colour,
};
pub struct Dielectric {
refraction_index: f32,
}
impl Dielectric {
pub fn new(refraction_index: f32) -> Self {
Self {
refraction_index: refraction_index,
}
}
}
impl Material for Dielectric {
fn scatter(&self, hit: &Hit, ray: &Ray) -> Option<(Ray, Colour)> {
let ri = if hit.front_face() {
1. / self.refraction_index
} else {
self.refraction_index
};
let unit = ray.dir().get_unit();
let refr = unit.refract(hit.n(), ri);
Some((Ray::new(*hit.p(), refr), Colour::new(1., 1., 1.)))
}
}

View File

@@ -4,6 +4,7 @@ use std::sync::Arc;
use crate::objects::hit::Hit;
use crate::objects::materials::traits::Material;
use crate::objects::traits::Hittable;
use crate::ray::Ray;
use crate::Vec3;
pub struct Sphere {
@@ -31,7 +32,7 @@ impl Sphere {
}
impl Hittable for Sphere {
fn hit(&self, r: &crate::ray::Ray) -> Option<Hit> {
fn hit(&self, r: &Ray) -> Option<Hit> {
let oc = self.center - r.origin();
let a = r.dir().length_squared();
let h = r.dir().dot(&oc);
@@ -43,7 +44,14 @@ 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), self.material.clone()))
let out_n = (p - self.center) / self.radius;
Some(Hit::new(
t,
p,
self.normal_at(&p),
self.material.clone(),
out_n.dot(r.dir()) < 0.,
))
}
}