Fix hopefully last nan for iridescent material

This commit is contained in:
hal8174 2025-05-28 19:08:38 +02:00
parent b1351747b7
commit 86d009fb4c
Signed by: hal8174
SSH key fingerprint: SHA256:JwuqS+eVfISfKr+DkDQ6NWAbGd1jFAHkPpCM1yCnlTs
3 changed files with 84 additions and 64 deletions

View file

@ -47,7 +47,7 @@ impl Iridescent {
let imag = (num_imag * denom_real - num_real * denom_imag) let imag = (num_imag * denom_real - num_real * denom_imag)
/ (denom_real * denom_real + denom_imag * denom_imag); / (denom_real * denom_real + denom_imag * denom_imag);
// if !real.is_normal() || !imag.is_normal() { // if real.is_nan() || imag.is_nan() {
// dbg!( // dbg!(
// l, theta1, theta2, s_polaized, r12, phi, num_real, num_imag, denom_real, // l, theta1, theta2, s_polaized, r12, phi, num_real, num_imag, denom_real,
// denom_imag, real, imag // denom_imag, real, imag
@ -57,13 +57,13 @@ impl Iridescent {
real * real + imag * imag real * real + imag * imag
} }
pub fn abs_C_squared(&self, l: f32, theta1: f32, theta2: f32, s_polaized: bool) -> f32 { pub fn abs_c_squared(&self, l: f32, theta1: f32, theta2: f32, s_polaized: bool) -> f32 {
let local_abs_r_1_squared = self.abs_r_1_squared(l, theta1, theta2, s_polaized); let local_abs_r_1_squared = self.abs_r_1_squared(l, theta1, theta2, s_polaized);
local_abs_r_1_squared / (1.0 - local_abs_r_1_squared) local_abs_r_1_squared / (1.0 - local_abs_r_1_squared)
} }
fn cos_K_Delta(&self, l: f32, theta1: f32, theta2: f32, s_polaized: bool) -> f32 { fn cos_k_delta(&self, l: f32, theta1: f32, theta2: f32, s_polaized: bool) -> f32 {
let k1z = 2.0 * f32::consts::PI * self.n1 * theta1.cos() / l; let k1z = 2.0 * f32::consts::PI * self.n1 * theta1.cos() / l;
let k2z = 2.0 * f32::consts::PI * self.n2 * theta2.cos() / l; let k2z = 2.0 * f32::consts::PI * self.n2 * theta2.cos() / l;
@ -81,11 +81,11 @@ impl Iridescent {
fn reflectance(&self, l: f32, theta1: f32, s_polaized: bool) -> f32 { fn reflectance(&self, l: f32, theta1: f32, s_polaized: bool) -> f32 {
let theta2 = f32::asin(f32::sin(theta1) * self.n1 / self.n2); let theta2 = f32::asin(f32::sin(theta1) * self.n1 / self.n2);
let local_cos_k_delta = self.cos_K_Delta(l, theta1, theta2, s_polaized); let local_cos_k_delta = self.cos_k_delta(l, theta1, theta2, s_polaized);
let local_c_squred = self.abs_C_squared(l, theta1, theta2, s_polaized); let local_c_squred = self.abs_c_squared(l, theta1, theta2, s_polaized);
// if !local_c_squred.is_normal() || !local_cos_k_delta.is_normal() { // if local_c_squred.is_nan() || local_cos_k_delta.is_nan() {
// dbg!(( // dbg!((
// l, // l,
// theta1, // theta1,
@ -96,62 +96,72 @@ impl Iridescent {
// )); // ));
// } // }
if local_cos_k_delta.abs() < 1.0 { if local_c_squred.is_infinite() {
let k_delta = f32::acos(local_cos_k_delta); 1.0
let u = f32::sin(k_delta) / f32::sin(self.n * k_delta);
// if !k_delta.is_normal() || !u.is_normal() {
// dbg!((
// l,
// theta1,
// theta2,
// local_cos_k_delta,
// local_c_squred,
// s_polaized,
// k_delta,
// u,
// ));
// }
local_c_squred / (local_c_squred + u * u)
} else if local_cos_k_delta.abs() > 1.0 {
let imk_delta = -f32::ln(f32::abs(
local_cos_k_delta - f32::sqrt(local_cos_k_delta * local_cos_k_delta - 1.0),
));
let u = f32::sinh(imk_delta) / f32::sinh(self.n * imk_delta);
// if !imk_delta.is_normal() || !u.is_normal() {
// dbg!((
// l,
// theta1,
// theta2,
// local_cos_k_delta,
// local_c_squred,
// s_polaized,
// imk_delta,
// u
// ));
// }
local_c_squred / (local_c_squred + u * u)
} else { } else {
let u = 1.0 / self.n; if local_cos_k_delta.abs() < 1.0 {
let k_delta = f32::acos(local_cos_k_delta);
// if !u.is_normal() { let u = f32::sin(k_delta) / f32::sin(self.n * k_delta);
// dbg!((
// l,
// theta1,
// theta2,
// local_cos_k_delta,
// local_c_squred,
// s_polaized,
// u
// ));
// }
local_c_squred / (local_c_squred + u * u) let r = local_c_squred / (local_c_squred + u * u);
// if k_delta.is_nan() || u.is_nan() || r.is_nan() {
// dbg!((
// l,
// theta1,
// theta2,
// local_cos_k_delta,
// local_c_squred,
// s_polaized,
// k_delta,
// u,
// r
// ));
// }
r
} else if local_cos_k_delta.abs() > 1.0 {
let imk_delta = -f32::ln(f32::abs(
local_cos_k_delta - f32::sqrt(local_cos_k_delta * local_cos_k_delta - 1.0),
));
let u = f32::sinh(imk_delta) / f32::sinh(self.n * imk_delta);
let r = local_c_squred / (local_c_squred + u * u);
// if imk_delta.is_nan() || u.is_nan() || r.is_nan() {
// dbg!((
// l,
// theta1,
// theta2,
// local_cos_k_delta,
// local_c_squred,
// s_polaized,
// imk_delta,
// u,
// r
// ));
// }
r
} else {
let u = 1.0 / self.n;
let r = local_c_squred / (local_c_squred + u * u);
// if u.is_nan() || r.is_nan() {
// dbg!((
// l,
// theta1,
// theta2,
// local_cos_k_delta,
// local_c_squred,
// s_polaized,
// u,
// r
// ));
// }
r
}
} }
} }
@ -189,13 +199,13 @@ impl Iridescent {
let r = self.averaged_reflectance(l, theta1); let r = self.averaged_reflectance(l, theta1);
// if !r.is_normal() { // if r.is_nan() {
// dbg!((theta1, l, r)); // dbg!((theta1, l, r));
// } // }
let color = Self::color_matching_function(l); let color = Self::color_matching_function(l);
// if !color.r().is_normal() || !color.g().is_normal() || !color.b().is_normal() { // if color.r().is_nan() || color.g().is_nan() || color.b().is_nan() {
// dbg!(color); // dbg!(color);
// } // }

View file

@ -33,6 +33,11 @@ pub fn example_scenes<R: Rng + Debug + 'static>() -> HashMap<&'static str, Box<d
"stanford_dragon_iridescent", "stanford_dragon_iridescent",
Box::new(stanford_dragon::StanfordDragon::new(material)), Box::new(stanford_dragon::StanfordDragon::new(material)),
); );
let material = Iridescent::new(0.9 * 988.0, 0.1 * 988.0, 1.0, 1.5, 20);
map.insert(
"stanford_dragon_iridescent2",
Box::new(stanford_dragon::StanfordDragon::new(material)),
);
let material = Mirror::new(Color::white()); let material = Mirror::new(Color::white());
map.insert( map.insert(
"stanford_dragon_mirror", "stanford_dragon_mirror",
@ -45,6 +50,7 @@ pub fn example_scenes<R: Rng + Debug + 'static>() -> HashMap<&'static str, Box<d
map.insert("mis_test", Box::new(mis_test::MISTest::new())); map.insert("mis_test", Box::new(mis_test::MISTest::new()));
let material = Iridescent::new(250.0, 250.0, 1.0, 1.3, 20); let material = Iridescent::new(250.0, 250.0, 1.0, 1.3, 20);
let material = Iridescent::new(0.9 * 988.0, 0.1 * 988.0, 1.0, 1.5, 20);
map.insert("sphere", Box::new(sphere::SphereScene::new(material))); map.insert("sphere", Box::new(sphere::SphereScene::new(material)));
map map
} }

View file

@ -51,9 +51,13 @@ fn render_image<
for _ in 0..samples_per_pixel { for _ in 0..samples_per_pixel {
let r = let r =
renderer.render_pixel(scene, camera, x, y, &mut rng) / (samples_per_pixel as Float); renderer.render_pixel(scene, camera, x, y, &mut rng) / (samples_per_pixel as Float);
c[0] += r.r(); if r.r().is_nan() || r.g().is_nan() || r.b().is_nan() {
c[1] += r.g(); eprintln!("NAN x: {:?}, y: {:?}, r: {:?}", x, y, r);
c[2] += r.b(); } else {
c[0] += r.r();
c[1] += r.g();
c[2] += r.b();
}
} }
}); });
println!("Rendered \"{}\" in {:?}", name.as_ref(), start.elapsed()); println!("Rendered \"{}\" in {:?}", name.as_ref(), start.elapsed());