Fix iridescent material

This commit is contained in:
hal8174 2025-05-26 20:52:47 +02:00
parent 543bf7e1bf
commit b1351747b7
Signed by: hal8174
SSH key fingerprint: SHA256:JwuqS+eVfISfKr+DkDQ6NWAbGd1jFAHkPpCM1yCnlTs
2 changed files with 45 additions and 20 deletions

View file

@ -1,17 +1,40 @@
use core::f32;
use plotters::{prelude::*, style::full_palette::GREEN};
use plotters::{coord::Shift, prelude::*, style::full_palette::GREEN};
use rand::{rngs::SmallRng, Rng, SeedableRng};
use ray_tracing_material::iridescent::Iridescent;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let root = BitMapBackend::new("iridescent_sweep.png", (800, 600)).into_drawing_area();
let root = BitMapBackend::new("iridescent_sweep.png", (2200, 1200)).into_drawing_area();
root.fill(&WHITE)?;
let mut chart = ChartBuilder::on(&root)
let d = root.split_evenly((3, 5));
let ds = [0.1, 0.3, 0.5, 0.7, 0.9];
let deltas = [244.0, 500.0, 988.0];
for (i, c) in d.into_iter().enumerate() {
draw_subplot(deltas[i / 5], 1.0 - ds[i % 5], &c)?;
}
root.present()?;
Ok(())
}
fn draw_subplot<DB: DrawingBackend>(
delta: f32,
d2: f32,
c: &DrawingArea<DB, Shift>,
) -> Result<(), Box<dyn std::error::Error>>
where
<DB as plotters::prelude::DrawingBackend>::ErrorType: 'static,
{
let mut chart = ChartBuilder::on(c)
.margin(5)
.x_label_area_size(30)
.y_label_area_size(30)
.build_cartesian_2d(0f32..f32::consts::FRAC_PI_2, 0f32..1f32)?;
.build_cartesian_2d(0f32..f32::consts::FRAC_PI_2, 0f32..1.1f32)?;
chart.configure_mesh().draw()?;
@ -20,7 +43,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let height_per_pixel = 1.0 / (pixel_range_y.end - pixel_range_y.start) as f32;
let samples = 10000;
let m = Iridescent::new(0.5 * 244.0, 0.5 * 244.0, 1.0, 1.5, 20);
let m = Iridescent::new((1.0 - d2) * delta, d2 * delta, 1.0, 1.5, 20);
let mut data = Vec::new();
@ -38,10 +61,16 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
);
s += m.monte_carlo_reflectance(theta1, &mut rng);
s_wavelength += ray_tracing_core::color::Color::new(
m.averaged_reflectance(595.0, theta1),
m.averaged_reflectance(599.0, theta1),
m.averaged_reflectance(556.0, theta1),
m.averaged_reflectance(442.0, theta1),
);
// let theta2 = f32::asin(f32::sin(theta1) * 1.0 / 1.5);
// s_wavelength += ray_tracing_core::color::Color::new(
// m.abs_C_squared(599.0, theta1, theta2, false),
// m.abs_C_squared(556.0, theta1, theta2, false),
// m.abs_C_squared(442.0, theta1, theta2, false),
// );
}
let c = s / samples as f32;
@ -49,12 +78,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// data.push(c);
data.push(s_wavelength / samples as f32);
// dbg!(c);
for j in 0..10 {
for j in 0..20 {
plotting_area
.draw_pixel(
(
f32::consts::FRAC_PI_2 * (i as f32 / buckets as f32),
1.0 - (height_per_pixel * (j as f32)),
1.1 - (height_per_pixel * (j as f32)),
),
&RGBColor(
(c.r() * 256.0) as u8,
@ -96,7 +125,5 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
&BLUE,
))?;
root.present()?;
Ok(())
}

View file

@ -22,26 +22,24 @@ impl Iridescent {
}
}
fn fresnel_reflection(&self, theta1: f32, theta2: f32, s_polaized: bool) -> f32 {
fn fresnel_reflection(n1: f32, n2: f32, theta1: f32, theta2: f32, s_polaized: bool) -> f32 {
if s_polaized {
(self.n1 * theta1.cos() - self.n2 * theta2.cos())
/ (self.n1 * theta1.cos() + self.n2 * theta2.cos())
(n1 * theta1.cos() - n2 * theta2.cos()) / (n1 * theta1.cos() + n2 * theta2.cos())
} else {
(self.n2 * theta1.cos() - self.n1 * theta2.cos())
/ (self.n2 * theta1.cos() + self.n1 * theta2.cos())
(n2 * theta1.cos() - n1 * theta2.cos()) / (n2 * theta1.cos() + n1 * theta2.cos())
}
}
fn abs_r_1_squared(&self, l: f32, theta1: f32, theta2: f32, s_polaized: bool) -> f32 {
let r12 = self.fresnel_reflection(theta1, theta2, s_polaized);
let r12 = Self::fresnel_reflection(self.n1, self.n2, theta1, theta2, s_polaized);
let phi = 2.0 * f32::consts::PI * self.n2 * self.d2 * theta2.cos() / l;
let num_real = r12 * (1.0 - f32::cos(-2.0 * phi));
let num_imag = r12 * (1.0 - f32::sin(-2.0 * phi));
let num_imag = r12 * (-1.0 * f32::sin(-2.0 * phi));
let denom_real = 1.0 - r12 * r12 * f32::cos(-2.0 * phi);
let denom_imag = 1.0 - r12 * r12 * f32::sin(-2.0 * phi);
let denom_imag = 0.0 - r12 * r12 * f32::sin(-2.0 * phi);
let real = (num_real * denom_real + num_imag * denom_imag)
/ (denom_real * denom_real + denom_imag * denom_imag);
@ -59,10 +57,10 @@ impl Iridescent {
real * real + imag * imag
}
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);
local_abs_r_1_squared / (local_abs_r_1_squared + 1.0)
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 {