Add eval to visualizer and fix pbr error
This commit is contained in:
parent
109a72c19a
commit
3a37a72f56
10 changed files with 105 additions and 55 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ pub trait Material<R: Rng>: 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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -68,6 +68,13 @@ impl Dir3 {
|
|||
Dir3::new(Float::sin(phi) * r, Float::cos(theta), Float::cos(phi) * r)
|
||||
}
|
||||
|
||||
pub fn sample_uniform_sphere<R: Rng>(rng: &mut R) -> Self {
|
||||
let theta = Float::acos(1.0 - 2.0 * rng.gen::<Float>());
|
||||
let phi = 2.0 * FloatConsts::PI * rng.gen::<Float>();
|
||||
let r = Float::sin(theta);
|
||||
Dir3::new(Float::sin(phi) * r, Float::cos(theta), Float::cos(phi) * r)
|
||||
}
|
||||
|
||||
pub fn sample_cosine_hemisphere<R: Rng>(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));
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "ray-tracing-material-validator"
|
||||
name = "ray-tracing-material-visualizer"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ pub fn scene<R: Rng + 'static>() -> ExampleScene<R> {
|
|||
},
|
||||
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)))),
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ pub fn scene<R: Rng + Debug + 'static>() -> ExampleScene<R> {
|
|||
.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)))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ pub fn scene<R: Rng + Debug + 'static>() -> ExampleScene<R> {
|
|||
|
||||
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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue