Add eval to visualizer and fix pbr error

This commit is contained in:
hal8174 2024-12-26 00:57:57 +01:00
parent 109a72c19a
commit 3a37a72f56
10 changed files with 105 additions and 55 deletions

View file

@ -1,5 +1,5 @@
[package]
name = "ray-tracing-material-validator"
name = "ray-tracing-material-visualizer"
version = "0.1.0"
edition = "2021"

View file

@ -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<dyn std::error::Error>> {
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(())
}

View file

@ -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<M: Material<SmallRng>>(
fn main() -> Result<(), Box<dyn std::error::Error>> {
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<M: Material<SmallRng>>(
path: impl AsRef<std::path::Path>,
m: &M,
samples_per_pixel: usize,
w_in: Dir3,
) -> Result<(), Box<dyn std::error::Error>> {
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<DB: DrawingBackend, M: Material<SmallRng>>(
fn plot_material<DB: DrawingBackend>(
root: &DrawingArea<DB, Shift>,
m: &M,
samples_per_pixel: usize,
histogram: Histogram,
max: Float,
) -> Result<(), Box<dyn std::error::Error>>
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<M: Material<SmallRng>>(
fn create_historgram_sampled<M: Material<SmallRng>>(
m: &M,
width: usize,
height: usize,
@ -237,3 +269,27 @@ fn create_historgram<M: Material<SmallRng>>(
h
}
fn create_histogram_evaled<M: Material<SmallRng>>(
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
}