Skip to content

Commit fff5d55

Browse files
committed
📫 Dielectric material
1 parent 7e99032 commit fff5d55

File tree

3 files changed

+85
-2
lines changed

3 files changed

+85
-2
lines changed

src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use vec3D::Vec3D;
1212
use hitable::HitableList;
1313
use sphere::Sphere;
1414
use camera::Camera;
15-
use material::{ Material, Lambert, Metal };
15+
use material::{ Material, Lambert, Metal, Dielectric };
1616
use utils::color;
1717

1818
fn main() {
@@ -47,7 +47,7 @@ fn main() {
4747
world.list.push(Box::new(Sphere::new(
4848
Vec3D::new(-1.0, 0.0, -1.0),
4949
0.5,
50-
Material::Metal(Metal::new(Vec3D::new(0.8, 0.8, 0.8), 1.0))
50+
Material::Dielectric(Dielectric::new(1.5))
5151
)));
5252

5353
let camera = Camera::new();

src/material.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ use crate::{
44
utils::{
55
random_in_unit_sphere,
66
reflect,
7+
refract,
8+
schlick,
79
},
810
};
911

@@ -17,13 +19,15 @@ pub trait Scatter {
1719
pub enum Material {
1820
Lambert(Lambert),
1921
Metal(Metal),
22+
Dielectric(Dielectric),
2023
}
2124

2225
impl Scatter for Material {
2326
fn scatter(&self, ray_in: &Ray, rec: &HitRecord, attenuation: &mut Vec3D, scattered: &mut Ray) -> bool {
2427
match self {
2528
Material::Lambert(material) => material.scatter(ray_in, rec, attenuation, scattered),
2629
Material::Metal(material) => material.scatter(ray_in, rec, attenuation, scattered),
30+
Material::Dielectric(material) => material.scatter(ray_in, rec, attenuation, scattered),
2731
}
2832
}
2933
}
@@ -67,6 +71,7 @@ impl Metal {
6771
}
6872
}
6973
}
74+
7075
impl Scatter for Metal {
7176
fn scatter(&self, ray_in: &Ray, rec: &HitRecord, attenuation: &mut Vec3D, scattered: &mut Ray) -> bool {
7277
let reflected = reflect(ray_in.direction.unit(), rec.normal);
@@ -79,3 +84,59 @@ impl Scatter for Metal {
7984
scattered.direction.dot(rec.normal) > 0.0
8085
}
8186
}
87+
88+
#[derive(Clone, Copy)]
89+
pub struct Dielectric {
90+
ref_idx: f64,
91+
}
92+
93+
impl Dielectric {
94+
pub fn new(ref_idx: f64) -> Dielectric {
95+
Dielectric {
96+
ref_idx
97+
}
98+
}
99+
}
100+
101+
impl Scatter for Dielectric {
102+
fn scatter(&self, ray_in: &Ray, rec: &HitRecord, attenuation: &mut Vec3D, scattered: &mut Ray) -> bool {
103+
let outward_normal: Vec3D;
104+
let ni_over_nt: f64;
105+
let mut refracted = Vec3D::new(0.0, 0.0, 0.0);
106+
let reflect_prob: f64;
107+
let cosine: f64;
108+
109+
let reflected = reflect(ray_in.direction.unit(), rec.normal);
110+
attenuation.x = 1.0;
111+
attenuation.y = 1.0;
112+
attenuation.z = 1.0;
113+
114+
if ray_in.direction.dot(rec.normal) > 0.0 {
115+
outward_normal = rec.normal * -1.0;
116+
ni_over_nt = self.ref_idx;
117+
cosine = self.ref_idx * ray_in.direction.dot(rec.normal) / ray_in.direction.mag();
118+
} else {
119+
outward_normal = rec.normal;
120+
ni_over_nt = 1.0 / self.ref_idx;
121+
cosine = ray_in.direction.dot(rec.normal) * -1.0 / ray_in.direction.mag();
122+
}
123+
124+
if refract(ray_in.direction, outward_normal, ni_over_nt, &mut refracted) {
125+
reflect_prob = schlick(cosine, self.ref_idx);
126+
} else {
127+
reflect_prob = 1.0;
128+
}
129+
130+
if rand::random::<f64>() < reflect_prob {
131+
// let new_scattered = Ray::new(rec.p, reflected);
132+
scattered.direction = reflected;
133+
scattered.origin = rec.p;
134+
} else {
135+
// let new_scattered = Ray::new(rec.p, refracted);
136+
scattered.direction = refracted;
137+
scattered.origin = rec.p;
138+
}
139+
140+
true
141+
}
142+
}

src/utils.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,25 @@ pub fn color(ray: Ray, world: &Hitable, depth: i32) -> Vec3D {
4646
pub fn reflect(v: Vec3D, n: Vec3D) -> Vec3D {
4747
v - n * v.dot(n) * 2.0
4848
}
49+
50+
pub fn refract(v: Vec3D, n: Vec3D, ni_over_nt: f64, refracted: &mut Vec3D) -> bool {
51+
let uv = v.unit();
52+
let dt = uv.dot(n);
53+
let discriminant = 1.0 - ni_over_nt * ni_over_nt * (1.0 - dt * dt);
54+
55+
if discriminant > 0.0 {
56+
let new_refracted = (uv - n * dt) * ni_over_nt - n * (discriminant.sqrt());
57+
refracted.x = new_refracted.x;
58+
refracted.y = new_refracted.y;
59+
refracted.z = new_refracted.z;
60+
return true;
61+
} else {
62+
return false;
63+
}
64+
}
65+
66+
pub fn schlick(cosine: f64, ref_idx: f64) -> f64 {
67+
let mut r0 = (1.0 - ref_idx) / (1.0 + ref_idx);
68+
r0 = r0 * r0;
69+
r0 + (1.0 - r0) * (1.0 - cosine).powi(5)
70+
}

0 commit comments

Comments
 (0)