ft (wip): 10: dielectrics
This commit is contained in:
@@ -8,6 +8,7 @@ mod vec3;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::camera::Camera;
|
use crate::camera::Camera;
|
||||||
|
use crate::objects::materials::dielectric::Dielectric;
|
||||||
use crate::objects::materials::lambertian::{Lambertian, Metal};
|
use crate::objects::materials::lambertian::{Lambertian, Metal};
|
||||||
use crate::objects::sphere::Sphere;
|
use crate::objects::sphere::Sphere;
|
||||||
use crate::ray::Ray;
|
use crate::ray::Ray;
|
||||||
@@ -21,7 +22,7 @@ fn main() {
|
|||||||
let metal = Arc::new(Metal::rgb(0.7, 0.4, 0.2, 1., 0.1));
|
let metal = Arc::new(Metal::rgb(0.7, 0.4, 0.2, 1., 0.1));
|
||||||
let ground = Arc::new(Lambertian::rgb(0.8, 0.8, 0., 1.0));
|
let ground = Arc::new(Lambertian::rgb(0.8, 0.8, 0., 1.0));
|
||||||
let center = Arc::new(Lambertian::rgb(0.1, 0.2, 0.5, 1.));
|
let center = Arc::new(Lambertian::rgb(0.1, 0.2, 0.5, 1.));
|
||||||
let left = Arc::new(Metal::rgb(0.8, 0.8, 0.8, 1., 0.3));
|
let left = Arc::new(Dielectric::new(1.5));
|
||||||
let right = Arc::new(Metal::rgb(0.8, 0.6, 0.2, 1., 1.0));
|
let right = Arc::new(Metal::rgb(0.8, 0.6, 0.2, 1., 1.0));
|
||||||
|
|
||||||
let mut world = vec![Sphere::xyz(0., 0.5, -0.8, 0.1, metal.clone())];
|
let mut world = vec![Sphere::xyz(0., 0.5, -0.8, 0.1, metal.clone())];
|
||||||
|
|||||||
@@ -11,15 +11,17 @@ pub struct Hit {
|
|||||||
p: Vec3,
|
p: Vec3,
|
||||||
n: Vec3,
|
n: Vec3,
|
||||||
mat: Arc<dyn Material>,
|
mat: Arc<dyn Material>,
|
||||||
|
front_face: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hit {
|
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 {
|
Self {
|
||||||
t: t,
|
t: t,
|
||||||
p: p,
|
p: p,
|
||||||
n: n,
|
n: if front_face { n } else { -n },
|
||||||
mat: mat,
|
mat: mat,
|
||||||
|
front_face: front_face,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,6 +41,10 @@ impl Hit {
|
|||||||
self.mat.clone()
|
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> {
|
pub fn hit_list<T: Hittable>(hittables: &Vec<T>, r: &Ray) -> Option<Hit> {
|
||||||
let mut closest: Option<Hit> = None;
|
let mut closest: Option<Hit> = None;
|
||||||
for hittable in hittables {
|
for hittable in hittables {
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
|
pub mod dielectric;
|
||||||
pub mod lambertian;
|
pub mod lambertian;
|
||||||
pub mod traits;
|
pub mod traits;
|
||||||
|
|||||||
30
src/objects/materials/dielectric.rs
Normal file
30
src/objects/materials/dielectric.rs
Normal 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.)))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ use std::sync::Arc;
|
|||||||
use crate::objects::hit::Hit;
|
use crate::objects::hit::Hit;
|
||||||
use crate::objects::materials::traits::Material;
|
use crate::objects::materials::traits::Material;
|
||||||
use crate::objects::traits::Hittable;
|
use crate::objects::traits::Hittable;
|
||||||
|
use crate::ray::Ray;
|
||||||
use crate::Vec3;
|
use crate::Vec3;
|
||||||
|
|
||||||
pub struct Sphere {
|
pub struct Sphere {
|
||||||
@@ -31,7 +32,7 @@ impl Sphere {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Hittable for 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 oc = self.center - r.origin();
|
||||||
let a = r.dir().length_squared();
|
let a = r.dir().length_squared();
|
||||||
let h = r.dir().dot(&oc);
|
let h = r.dir().dot(&oc);
|
||||||
@@ -43,7 +44,14 @@ impl Hittable for Sphere {
|
|||||||
} else {
|
} else {
|
||||||
let t = (h - sqrt(d)) / a;
|
let t = (h - sqrt(d)) / a;
|
||||||
let p = r.at(t);
|
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.,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
22
src/vec3.rs
22
src/vec3.rs
@@ -101,8 +101,18 @@ impl Vec3 {
|
|||||||
&& default().is_close(self.b, 0.)
|
&& default().is_close(self.b, 0.)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reflect(&self, o: &Vec3) -> Vec3 {
|
pub fn reflect(&self, n: &Self) -> Self {
|
||||||
*self - 2. * self.dot(o) * o
|
*self - 2. * self.dot(n) * n
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn refract(&self, n: &Self, etai_over_etat: f32) -> Self {
|
||||||
|
let mut cos_theta = -self.dot(n);
|
||||||
|
cos_theta = if cos_theta > 1.0 { 1.0 } else { cos_theta };
|
||||||
|
|
||||||
|
let r_out_perp = etai_over_etat * (*self + cos_theta * n);
|
||||||
|
let r_out_parr = -sqrt((1. - r_out_perp.length_squared()).abs()) * n;
|
||||||
|
|
||||||
|
return r_out_perp + r_out_parr;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn output(self) -> image::Rgb<u8> {
|
pub fn output(self) -> image::Rgb<u8> {
|
||||||
@@ -139,6 +149,14 @@ impl Vec3 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Neg for &Vec3 {
|
||||||
|
type Output = Vec3;
|
||||||
|
|
||||||
|
fn neg(self) -> Self::Output {
|
||||||
|
-*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Neg for Vec3 {
|
impl Neg for Vec3 {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user