summaryrefslogtreecommitdiff
path: root/racer-tracer/src/material
diff options
context:
space:
mode:
authorSakarias Johansson <sakarias.johansson@goodbyekansas.com>2023-01-16 20:58:55 +0100
committerSakarias Johansson <sakarias.johansson@goodbyekansas.com>2023-01-16 20:58:55 +0100
commit03e5a88f9b7da79749370685e8f5afaf03a25b4a (patch)
tree9e0fd5e12bcd9739f5292864c9da9084a0030489 /racer-tracer/src/material
parent3167ec992f1f81b2252a2db3642fff943c4f14bf (diff)
downloadracer-tracer-03e5a88f9b7da79749370685e8f5afaf03a25b4a.tar.gz
racer-tracer-03e5a88f9b7da79749370685e8f5afaf03a25b4a.tar.xz
racer-tracer-03e5a88f9b7da79749370685e8f5afaf03a25b4a.zip
🎨 Add dialectric material
Diffstat (limited to 'racer-tracer/src/material')
-rw-r--r--racer-tracer/src/material/dialectric.rs53
1 files changed, 53 insertions, 0 deletions
diff --git a/racer-tracer/src/material/dialectric.rs b/racer-tracer/src/material/dialectric.rs
new file mode 100644
index 0000000..5f3aa02
--- /dev/null
+++ b/racer-tracer/src/material/dialectric.rs
@@ -0,0 +1,53 @@
+use crate::{
+ material::Material,
+ ray::Ray,
+ util::random_double,
+ vec3::{dot, reflect, refract, Color},
+};
+
+pub struct Dialectric {
+ refraction_index: f64,
+}
+
+impl Dialectric {
+ pub fn new(refraction_index: f64) -> Self {
+ Self { refraction_index }
+ }
+
+ fn reflectance(cosine: f64, refraction_index: f64) -> f64 {
+ // Schlick approximation
+ let mut r0 = (1.0 - refraction_index) / (1.0 + refraction_index);
+ r0 = r0 * r0;
+ r0 + (1.0 - r0) * (1.0 - cosine).powf(5.0)
+ }
+}
+
+impl Material for Dialectric {
+ fn scatter(
+ &self,
+ ray: &crate::ray::Ray,
+ rec: &crate::geometry::HitRecord,
+ ) -> Option<(Ray, Color)> {
+ let refraction_ratio = if rec.front_face {
+ 1.0 / self.refraction_index
+ } else {
+ self.refraction_index
+ };
+
+ let unit_direction = &ray.direction().unit_vector();
+ let cos_theta = f64::min(dot(&-unit_direction, &rec.normal), 1.0);
+ let sin_theta = f64::sqrt(1.0 - cos_theta * cos_theta);
+
+ let cannot_refract = refraction_ratio * sin_theta > 1.0;
+
+ let direction = if cannot_refract
+ || Dialectric::reflectance(cos_theta, refraction_ratio) > random_double()
+ {
+ reflect(unit_direction, &rec.normal)
+ } else {
+ refract(unit_direction, &rec.normal, refraction_ratio)
+ };
+
+ Some((Ray::new(rec.point, direction), Color::new(1.0, 1.0, 1.0)))
+ }
+}