From 3a37a72f56d099225a45d2928a5f3fb821d6e2e6 Mon Sep 17 00:00:00 2001 From: hal8174 Date: Thu, 26 Dec 2024 00:57:57 +0100 Subject: [PATCH] Add eval to visualizer and fix pbr error --- Cargo.lock | 4 +- ray-tracing-core/src/material.rs | 2 +- ray-tracing-core/src/math/dir3.rs | 7 + ray-tracing-material-visualizer/Cargo.toml | 2 +- .../src/bin/plot.rs | 13 -- .../src/{lib.rs => main.rs} | 124 +++++++++++++----- ray-tracing-renderer/src/path_tracer.rs | 2 +- .../src/examples/basic_cornell.rs | 2 +- ray-tracing-scene/src/examples/cornell2.rs | 2 +- .../src/examples/stanford_dragon.rs | 2 +- 10 files changed, 105 insertions(+), 55 deletions(-) delete mode 100644 ray-tracing-material-visualizer/src/bin/plot.rs rename ray-tracing-material-visualizer/src/{lib.rs => main.rs} (64%) diff --git a/Cargo.lock b/Cargo.lock index 4f631e8..fc87a4d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "ab_glyph" @@ -2205,7 +2205,7 @@ dependencies = [ ] [[package]] -name = "ray-tracing-material-validator" +name = "ray-tracing-material-visualizer" version = "0.1.0" dependencies = [ "plotters", diff --git a/ray-tracing-core/src/material.rs b/ray-tracing-core/src/material.rs index fcee353..c9869af 100644 --- a/ray-tracing-core/src/material.rs +++ b/ray-tracing-core/src/material.rs @@ -8,7 +8,7 @@ pub trait Material: Sync + Debug { fn sample(&self, w_in: Dir3, rng: &mut R) -> SampleResult { let w_out = Dir3::sample_cosine_hemisphere(rng); - SampleResult::new(w_out, self.eval(w_in, w_out, rng)) + SampleResult::new(w_out, self.eval(w_in, w_out, rng) * FloatConsts::PI) } } diff --git a/ray-tracing-core/src/math/dir3.rs b/ray-tracing-core/src/math/dir3.rs index f38ecd8..e6684bb 100644 --- a/ray-tracing-core/src/math/dir3.rs +++ b/ray-tracing-core/src/math/dir3.rs @@ -68,6 +68,13 @@ impl Dir3 { Dir3::new(Float::sin(phi) * r, Float::cos(theta), Float::cos(phi) * r) } + pub fn sample_uniform_sphere(rng: &mut R) -> Self { + let theta = Float::acos(1.0 - 2.0 * rng.gen::()); + let phi = 2.0 * FloatConsts::PI * rng.gen::(); + let r = Float::sin(theta); + Dir3::new(Float::sin(phi) * r, Float::cos(theta), Float::cos(phi) * r) + } + pub fn sample_cosine_hemisphere(rng: &mut R) -> Self { let mut d = Self::sample_disc(rng); d.y = Float::sqrt(Float::max(0.0, 1.0 - d.x * d.x - d.z * d.z)); diff --git a/ray-tracing-material-visualizer/Cargo.toml b/ray-tracing-material-visualizer/Cargo.toml index 04b7151..1c19be7 100644 --- a/ray-tracing-material-visualizer/Cargo.toml +++ b/ray-tracing-material-visualizer/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "ray-tracing-material-validator" +name = "ray-tracing-material-visualizer" version = "0.1.0" edition = "2021" diff --git a/ray-tracing-material-visualizer/src/bin/plot.rs b/ray-tracing-material-visualizer/src/bin/plot.rs deleted file mode 100644 index ba20d6e..0000000 --- a/ray-tracing-material-visualizer/src/bin/plot.rs +++ /dev/null @@ -1,13 +0,0 @@ -use ray_tracing_core::color::Color; -use ray_tracing_material::{diffuse::DiffuseMaterial, mirror::Mirror}; -use ray_tracing_material_validator::generate_chart; - -fn main() -> Result<(), Box> { - let m = Mirror::new(Color::new(1.0, 1.0, 0.5)); - generate_chart("mirror.png", &m, 2)?; - - let m = DiffuseMaterial::new(Color::new(1.0, 1.0, 0.5)); - generate_chart("diffuse.png", &m, 100)?; - - Ok(()) -} diff --git a/ray-tracing-material-visualizer/src/lib.rs b/ray-tracing-material-visualizer/src/main.rs similarity index 64% rename from ray-tracing-material-visualizer/src/lib.rs rename to ray-tracing-material-visualizer/src/main.rs index 095ab6d..37a46a5 100644 --- a/ray-tracing-material-visualizer/src/lib.rs +++ b/ray-tracing-material-visualizer/src/main.rs @@ -1,51 +1,68 @@ -use plotters::{coord::Shift, prelude::*}; +use plotters::{ + chart::ChartBuilder, + coord::Shift, + prelude::{BitMapBackend, DrawingArea, DrawingBackend, IntoDrawingArea}, + style::WHITE, +}; use rand::{rngs::SmallRng, SeedableRng}; -use ray_tracing_core::{color::Color, prelude::*}; -use rayon::prelude::*; +use ray_tracing_core::prelude::*; +use ray_tracing_material::{diffuse::DiffuseMaterial, mirror::Mirror}; +use rayon::iter::{IntoParallelIterator, ParallelExtend, ParallelIterator}; -pub fn generate_chart>( +fn main() -> Result<(), Box> { + let w_in = Dir3::new(1.0, 1.0, 0.0).normalize(); + + let color = Color::new(1.0, 1.0, 1.0); + + let m = Mirror::new(color); + generate_chart("mirror.png", &m, 2, w_in)?; + + let m = DiffuseMaterial::new(color); + generate_chart("diffuse.png", &m, 100, w_in)?; + + Ok(()) +} + +fn generate_chart>( path: impl AsRef, m: &M, samples_per_pixel: usize, + w_in: Dir3, ) -> Result<(), Box> { let inner_size = 400; - let width = (inner_size + 70) * 3 + 34; - let height = (inner_size + 97) * 2; + let width = (inner_size + 70) * 3; + let height = ((inner_size + 97) * 2 + 32) * 2; let root = BitMapBackend::new(&path, (width, height)).into_drawing_area(); - root.fill(&WHITE)?; - let area = root.titled("Sampled", ("sans-serif", 30))?; - plot_material_sample(&area, m, samples_per_pixel)?; + let executions = inner_size as usize * inner_size as usize * samples_per_pixel; + + let areas = root.split_evenly((2, 1)); + let eval_histogram = create_histogram_evaled(m, 400, 400, executions, w_in); + let sample_histogram = create_historgram_sampled(m, 400, 400, executions, w_in); + + let max = Float::max(eval_histogram.max(), sample_histogram.max()); + dbg!(max, eval_histogram.max(), sample_histogram.max()); + + let area = areas[0].titled("Evaled", ("sans-serif", 30))?; + plot_material(&area, eval_histogram, max)?; + + let area = areas[1].titled("Sampled", ("sans-serif", 30))?; + plot_material(&area, sample_histogram, max)?; root.present()?; Ok(()) } -fn plot_material_sample>( +fn plot_material( root: &DrawingArea, - m: &M, - samples_per_pixel: usize, + histogram: Histogram, + max: Float, ) -> Result<(), Box> where DB::ErrorType: 'static, { - let (xrange, yrange) = root.get_pixel_range(); - let width = (xrange.end - xrange.start) as usize; - let height = (yrange.end - yrange.start) as usize; - - let width = width / 3 - 70; - let height = height / 2 - 97; - - let histogram = create_historgram( - m, - width, - height, - samples_per_pixel * width * height, - Dir3::new(1.0, 1.0, 0.0).normalize(), - ); - let areas = root.split_evenly((2, 3)); for (channel, upper, lower) in (0..3).map(|i| (i, &areas[i], &areas[i + 3])) { let channel_name = match channel { @@ -95,9 +112,17 @@ where let lower_area = lower_chart.plotting_area(); - let map = ViridisRGB; + let (xrange, yrange) = upper_area.get_pixel_range(); + let width = (xrange.end - xrange.start) as usize; + let height = (yrange.end - yrange.start) as usize; + assert_eq!(width, histogram.width); + assert_eq!(height, histogram.height); - let max = histogram.max(); + let (xrange, yrange) = lower_area.get_pixel_range(); + let width = (xrange.end - xrange.start) as usize; + let height = (yrange.end - yrange.start) as usize; + assert_eq!(width, histogram.width); + assert_eq!(height, histogram.height); for (dir, f) in histogram.iter() { let f = match channel { @@ -107,7 +132,7 @@ where _ => unreachable!(), }; - let color = map.get_color_normalized(f, 0.0, max); + let color = plotters::prelude::ViridisRGB::get_color_normalized(f, 0.0, max); if dir.y() < 0.0 { lower_area.draw_pixel((dir.x() as f64, dir.z() as f64), &color)?; } else { @@ -139,10 +164,17 @@ impl Histogram { } fn discretize(&self, p: Dir3) -> usize { - (((p.x() + 1.0) * 0.5 * self.width as f32).floor() as usize) - + (((p.z() + 1.0) * 0.5 * self.height as f32).floor() as usize) * self.width + assert!(p.x() >= -1.0); + assert!(p.x() <= 1.0); + assert!(p.y() >= -1.0); + assert!(p.y() <= 1.0); + assert!(p.z() >= -1.0); + assert!(p.z() <= 1.0); + (((p.x() + 1.0) * 0.5 * self.width as f32).floor() as usize).min(self.width - 1) + + (((p.z() + 1.0) * 0.5 * self.height as f32).floor() as usize).min(self.height - 1) + * self.width + if p.y() < 0.0 { - 2 * self.width * self.height + self.width * self.height } else { 0 } @@ -217,7 +249,7 @@ impl ParallelExtend<(Dir3, Color)> for Histogram { } } -fn create_historgram>( +fn create_historgram_sampled>( m: &M, width: usize, height: usize, @@ -237,3 +269,27 @@ fn create_historgram>( h } + +fn create_histogram_evaled>( + m: &M, + width: usize, + height: usize, + executions: usize, + w_in: Dir3, +) -> Histogram { + let mut h = Histogram::new(width, height); + + h.par_extend( + (0..executions) + .into_par_iter() + .map_init(SmallRng::from_entropy, |rng, _| { + let w_out = Dir3::sample_uniform_sphere(rng); + + let color = m.eval(w_in, w_out, rng) * w_out.y() * 4.0 * FloatConsts::PI; + + (w_out, color) + }), + ); + + h +} diff --git a/ray-tracing-renderer/src/path_tracer.rs b/ray-tracing-renderer/src/path_tracer.rs index dafe454..46a13db 100644 --- a/ray-tracing-renderer/src/path_tracer.rs +++ b/ray-tracing-renderer/src/path_tracer.rs @@ -47,7 +47,7 @@ where } if let Some(material) = i.material() { - alpha *= material.eval(w_in, w_out, rng) * w_out.y(); + alpha *= material.eval(w_in, w_out, rng) * w_out.y() * 2.0 * FloatConsts::PI; } else { return sum; } diff --git a/ray-tracing-scene/src/examples/basic_cornell.rs b/ray-tracing-scene/src/examples/basic_cornell.rs index 598ca7e..b8f8fe6 100644 --- a/ray-tracing-scene/src/examples/basic_cornell.rs +++ b/ray-tracing-scene/src/examples/basic_cornell.rs @@ -64,7 +64,7 @@ pub fn scene() -> ExampleScene { }, BVHMaterial { material: None, - light: Some(Box::new(AreaLight::new(Color::white() * 30.0))), + light: Some(Box::new(AreaLight::new(Color::white() * 18.0))), }, BVHMaterial { material: Some(Box::new(Mirror::new(Color::new(1.0, 1.0, 1.0)))), diff --git a/ray-tracing-scene/src/examples/cornell2.rs b/ray-tracing-scene/src/examples/cornell2.rs index 01277c1..b953169 100644 --- a/ray-tracing-scene/src/examples/cornell2.rs +++ b/ray-tracing-scene/src/examples/cornell2.rs @@ -24,7 +24,7 @@ pub fn scene() -> ExampleScene { .iter() .map(|m| match m.name.as_str() { "white" => BVHMaterial::new_material(DiffuseMaterial::new(Color::white())), - "light" => BVHMaterial::new_light(AreaLight::new(Color::white() * 100.0)), + "light" => BVHMaterial::new_light(AreaLight::new(Color::white() * 30.0)), "blue" => { BVHMaterial::new_material(DiffuseMaterial::new(Color::new(0.0, 0.0, 1.0))) } diff --git a/ray-tracing-scene/src/examples/stanford_dragon.rs b/ray-tracing-scene/src/examples/stanford_dragon.rs index e2236b4..fe7f41d 100644 --- a/ray-tracing-scene/src/examples/stanford_dragon.rs +++ b/ray-tracing-scene/src/examples/stanford_dragon.rs @@ -21,7 +21,7 @@ pub fn scene() -> ExampleScene { let materials = vec![ BVHMaterial::new_material(DiffuseMaterial::new(Color::new(0.2, 0.2, 0.9))), - BVHMaterial::new_light(AreaLight::new(Color::white() * 100.0)), + BVHMaterial::new_light(AreaLight::new(Color::white() * 30.0)), ]; let mut vertices = obj.vertices;