Fix hit determination inside a sphere

master
Max Nuding 2022-07-02 06:30:42 +02:00
parent 89a2333644
commit 46ec8663ff
Signed by: phlaym
GPG Key ID: 0AAD39863E09DC48
5 changed files with 9 additions and 23 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@
*.ppm *.ppm
.idea .idea
*.iml *.iml
.vscode/

View File

@ -42,16 +42,16 @@ impl Hittable for Sphere {
let discriminant = half_b * half_b - a * c; let discriminant = half_b * half_b - a * c;
if discriminant < 0.0 { return None; } if discriminant < 0.0 { return None; }
let sqrtd = f64::sqrt(discriminant); let sqrtd = discriminant.sqrt();
let root = (-half_b - sqrtd) / a; let mut root = (-half_b - sqrtd) / a;
if root < t_min || t_max < root { if root < t_min || t_max < root {
let root = (-half_b + sqrtd) / a; root = (-half_b + sqrtd) / a;
if root < t_min || t_max < root { return None; } if root < t_min || t_max < root { return None; }
} }
let point = ray.at(root); let point = ray.at(root);
let normal = (point - self.center) / self.radius; let normal = (point - self.center) / self.radius;
let front_face = ray.direction().dot(&normal) < 0.0; let dot = ray.direction().dot(&normal);
let front_face = dot < 0.0;
let normal = if front_face { normal } else { -normal }; let normal = if front_face { normal } else { -normal };
Some(HitRecord { Some(HitRecord {
point, point,

View File

@ -104,6 +104,7 @@ impl Scatterable for Dielectric {
self.index_of_refraction self.index_of_refraction
}; };
let unit_direction = ray.direction().unit_vector(); let unit_direction = ray.direction().unit_vector();
let cos_theta = ((-unit_direction).dot(&hit_record.normal)).min(1.0); let cos_theta = ((-unit_direction).dot(&hit_record.normal)).min(1.0);
let sin_theta = (1.0 - cos_theta*cos_theta).sqrt(); let sin_theta = (1.0 - cos_theta*cos_theta).sqrt();
let cannot_refract = refraction_ratio * sin_theta > 1.0; let cannot_refract = refraction_ratio * sin_theta > 1.0;
@ -112,12 +113,10 @@ impl Scatterable for Dielectric {
if cannot_refract || reflectance > rng.gen::<f64>() { if cannot_refract || reflectance > rng.gen::<f64>() {
let reflected = unit_direction.reflected(&hit_record.normal); let reflected = unit_direction.reflected(&hit_record.normal);
let reflected = Vec3::new(-reflected.x(), reflected.y(), -reflected.z());
let scattered = Ray::new(hit_record.point, reflected); let scattered = Ray::new(hit_record.point, reflected);
Some((Some(scattered), color)) Some((Some(scattered), color))
} else { } else {
//let direction = unit_direction.refract(&hit_record.normal, refraction_ratio); let direction = unit_direction.refract(&hit_record.normal, refraction_ratio);
let direction = unit_direction.refract_sort_of_works(&hit_record.normal, refraction_ratio);
let scattered = Ray::new(hit_record.point, direction); let scattered = Ray::new(hit_record.point, direction);
Some((Some(scattered), color)) Some((Some(scattered), color))
} }

View File

@ -3,6 +3,7 @@ use crate::hittable::HitRecord;
use crate::material::Scatterable; use crate::material::Scatterable;
use crate::vec3::Point3; use crate::vec3::Point3;
#[derive(Debug)]
pub struct Ray { pub struct Ray {
origin: Point3, origin: Point3,
direction: Vec3 direction: Vec3

View File

@ -84,21 +84,6 @@ impl Vec3 {
let out_parallel = r * (*normal); let out_parallel = r * (*normal);
out_perp + out_parallel out_perp + out_parallel
} }
pub fn refract_sort_of_works(&self, normal: &Vec3, etai_over_etat: f64) -> Vec3 {
let dot = (-(*self)).dot(normal);
let cos_theta = dot.min(1.0);
let out_perp = etai_over_etat * ((*self) + cos_theta * (*normal));
let inner = 1.0 - out_perp.length_squared();
let abs = inner.abs();
let r = -(abs.sqrt());
let out_parallel = r * (*normal);
// Why?
let mut res = out_perp + out_parallel;
res.x = -res.x;
//res.y = -res.y;
res.z = -res.z;
res
}
} }
#[test] #[test]