rtiow: Many changes
Add debugging hit DebugHit. Move some color helpers from mandelbrot to colors mod. Implement Texture trait for [f32;3]
This commit is contained in:
46
rtiow/renderer/src/colors.rs
Normal file
46
rtiow/renderer/src/colors.rs
Normal file
@@ -0,0 +1,46 @@
|
||||
use rand::{self, Rng};
|
||||
|
||||
use crate::vec3::Vec3;
|
||||
|
||||
// HSV values in [0..1]
|
||||
// returns [r, g, b] values from 0 to 255
|
||||
//From https://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
|
||||
pub fn hsv_to_rgb(h: f32, s: f32, v: f32) -> Vec3 {
|
||||
let h_i = (h * 6.) as i32;
|
||||
let f = h * 6. - h_i as f32;
|
||||
let p = v * (1. - s);
|
||||
let q = v * (1. - f * s);
|
||||
let t = v * (1. - (1. - f) * s);
|
||||
match h_i {
|
||||
0 => Vec3::new(v, t, p),
|
||||
1 => Vec3::new(q, v, p),
|
||||
2 => Vec3::new(p, v, t),
|
||||
3 => Vec3::new(p, q, v),
|
||||
4 => Vec3::new(t, p, v),
|
||||
5 => Vec3::new(v, p, q),
|
||||
_ => panic!("Unknown H value {}", h_i),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_rainbow(num: usize) -> Vec<Vec3> {
|
||||
(0..num)
|
||||
.map(|n| {
|
||||
let h = n as f32 / num as f32;
|
||||
hsv_to_rgb(h, 0.99, 0.99)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
pub fn generate_palette(num: usize) -> Vec<Vec3> {
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut random = || rng.gen();
|
||||
// use golden ratio
|
||||
let golden_ratio_conjugate = 0.618_034;
|
||||
let mut h = random();
|
||||
(0..num)
|
||||
.map(|_| {
|
||||
h += golden_ratio_conjugate;
|
||||
h %= 1.0;
|
||||
hsv_to_rgb(h, 0.99, 0.99)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
46
rtiow/renderer/src/debug_hit.rs
Normal file
46
rtiow/renderer/src/debug_hit.rs
Normal file
@@ -0,0 +1,46 @@
|
||||
use crate::{
|
||||
aabb::AABB,
|
||||
hitable::{Hit, HitRecord},
|
||||
material::Lambertian,
|
||||
ray::Ray,
|
||||
texture::{self, ConstantTexture},
|
||||
vec3::Vec3,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DebugHit<H>
|
||||
where
|
||||
H: Hit,
|
||||
{
|
||||
hitable: H,
|
||||
material: Lambertian<[f32; 3]>,
|
||||
}
|
||||
|
||||
impl<H> DebugHit<H>
|
||||
where
|
||||
H: Hit,
|
||||
{
|
||||
pub fn new(hitable: H) -> DebugHit<H>
|
||||
where {
|
||||
DebugHit {
|
||||
hitable,
|
||||
material: Lambertian::new([0.2, 0.2, 0.2]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<H> Hit for DebugHit<H>
|
||||
where
|
||||
H: Hit,
|
||||
{
|
||||
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord> {
|
||||
if let Some(hit) = self.hitable.hit(r, t_min, t_max) {
|
||||
return Some(HitRecord { t: hit.t, ..hit });
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn bounding_box(&self, t_min: f32, t_max: f32) -> Option<AABB> {
|
||||
self.hitable.bounding_box(t_min, t_max)
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,10 @@ pub mod aabb;
|
||||
pub mod bvh;
|
||||
pub mod bvh_triangles;
|
||||
pub mod camera;
|
||||
pub mod colors;
|
||||
pub mod constant_medium;
|
||||
pub mod cuboid;
|
||||
pub mod debug_hit;
|
||||
pub mod flip_normals;
|
||||
pub mod glowybox;
|
||||
pub mod hitable;
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
use std::io::{BufReader, Cursor};
|
||||
use std::{
|
||||
f32::consts::PI,
|
||||
io::{BufReader, Cursor},
|
||||
iter::Inspect,
|
||||
};
|
||||
|
||||
use stl::STL;
|
||||
|
||||
use crate::{
|
||||
bvh_triangles::BVHTriangles,
|
||||
camera::Camera,
|
||||
colors::generate_rainbow,
|
||||
hitable::Hit,
|
||||
hitable_list::HitableList,
|
||||
kdtree::KDTree,
|
||||
material::{Dielectric, Lambertian},
|
||||
material::{Dielectric, Lambertian, Metal},
|
||||
renderer::{Opt, Scene},
|
||||
rotate::RotateY,
|
||||
scale::Scale,
|
||||
sphere::Sphere,
|
||||
texture::{ConstantTexture, EnvMap},
|
||||
@@ -18,8 +24,8 @@ use crate::{
|
||||
};
|
||||
|
||||
pub fn new(opt: &Opt) -> Scene {
|
||||
let lookfrom = Vec3::new(0., 40., -100.);
|
||||
let lookat = Vec3::new(0., 10., 0.);
|
||||
let lookfrom = Vec3::new(0., 80., 80.);
|
||||
let lookat = Vec3::new(0., 0., 0.);
|
||||
let dist_to_focus = 10.0;
|
||||
let aperture = 0.0;
|
||||
let time_min = 0.;
|
||||
@@ -35,6 +41,10 @@ pub fn new(opt: &Opt) -> Scene {
|
||||
time_min,
|
||||
time_max,
|
||||
);
|
||||
//let dragon_material = Dielectric::new(1.5);
|
||||
let dragon_material = Metal::new(Vec3::new(0.6, 0.6, 0.6), 0.0);
|
||||
//let dragon_material = Lambertian::new(ConstantTexture::new(Vec3::new(1.0, 1.0, 0.2)));
|
||||
|
||||
let ground_color = if opt.use_accel {
|
||||
ConstantTexture::new(Vec3::new(1.0, 0.4, 0.4))
|
||||
} else {
|
||||
@@ -42,46 +52,51 @@ pub fn new(opt: &Opt) -> Scene {
|
||||
};
|
||||
|
||||
let stl_cube = STL::parse(
|
||||
BufReader::new(Cursor::new(include_bytes!(
|
||||
"../../stls/stanford_dragon-lowres.stl" //"../../stls/stanford_dragon.stl"
|
||||
))),
|
||||
BufReader::new(Cursor::new(include_bytes!("../../stls/dragon.stl"))),
|
||||
//BufReader::new(Cursor::new(include_bytes!("../../stls/cube.stl"))),
|
||||
false,
|
||||
)
|
||||
.expect("failed to parse cube");
|
||||
let _light_size = 50.;
|
||||
let _light_height = 200.;
|
||||
let objects: Vec<Box<dyn Hit>> = vec![
|
||||
// Light from above - white
|
||||
let sphere_radius = 5.;
|
||||
let circle_radius = 40.;
|
||||
let num_spheres = 16;
|
||||
let palette = generate_rainbow(num_spheres);
|
||||
let spheres: Vec<Box<dyn Hit>> = (0..num_spheres)
|
||||
.map(|i| (i, i as f32, num_spheres as f32))
|
||||
.map(|(idx, idx_f, n)| (idx, idx_f * 2. * PI / n))
|
||||
.map(|(idx, rad)| -> Box<dyn Hit> {
|
||||
let x = circle_radius * rad.cos();
|
||||
let y = 4. * sphere_radius;
|
||||
let z = circle_radius * rad.sin();
|
||||
let c = palette[idx];
|
||||
Box::new(Sphere::new(
|
||||
[x, y, z],
|
||||
sphere_radius,
|
||||
Lambertian::new(ConstantTexture::new(c)),
|
||||
))
|
||||
})
|
||||
.collect();
|
||||
let mut objects: Vec<Box<dyn Hit>> = vec![
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(0., 0.1, -0.5),
|
||||
0.1,
|
||||
Lambertian::new([0., 1., 1.]),
|
||||
)),
|
||||
// Earth sized sphere
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(0., -10000., 0.),
|
||||
10000.,
|
||||
Lambertian::new(ground_color),
|
||||
)),
|
||||
// Blue sphere
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(0., 20., 40.),
|
||||
20.,
|
||||
Lambertian::new(ConstantTexture::new(Vec3::new(0.2, 0.2, 1.))),
|
||||
)),
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(40., 20., 40.),
|
||||
20.,
|
||||
//Metal::new(Vec3::new(0.8, 0.8, 0.8), 0.2),
|
||||
Lambertian::new(ConstantTexture::new(Vec3::new(0.2, 1.0, 0.2))),
|
||||
)),
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(-40., 20., 40.),
|
||||
20.,
|
||||
//Metal::new(Vec3::new(0.8, 0.8, 0.8), 0.2),
|
||||
Lambertian::new(ConstantTexture::new(Vec3::new(1.0, 0.2, 0.2))),
|
||||
)),
|
||||
//Box::new(Sphere::new( Vec3::new(0., -10000., 0.), 10000., Lambertian::new(ground_color),)),
|
||||
// STL Mesh
|
||||
Box::new(Translate::new(
|
||||
Scale::new(BVHTriangles::new(&stl_cube, Dielectric::new(1.5)), 250.),
|
||||
[0., -10., 0.],
|
||||
)),
|
||||
Box::new(crate::debug_hit::DebugHit::new(RotateY::new(
|
||||
Translate::new(
|
||||
Scale::new(BVHTriangles::new(&stl_cube, dragon_material), 250.),
|
||||
[0., -10., 0.],
|
||||
),
|
||||
180.,
|
||||
))),
|
||||
];
|
||||
objects.extend(spheres);
|
||||
|
||||
let world: Box<dyn Hit> = if opt.use_accel {
|
||||
Box::new(KDTree::new(objects, time_min, time_max))
|
||||
} else {
|
||||
|
||||
@@ -16,6 +16,7 @@ use crate::{
|
||||
renderer::{Opt, Scene},
|
||||
sphere::Sphere,
|
||||
texture::{ConstantTexture, EnvMap},
|
||||
translate::Translate,
|
||||
vec3::Vec3,
|
||||
};
|
||||
|
||||
@@ -47,7 +48,7 @@ pub fn new(opt: &Opt) -> Scene {
|
||||
let metal = Metal::new(Vec3::new(0.8, 0.8, 0.8), 0.2);
|
||||
let red = Lambertian::new(ConstantTexture::new(Vec3::new(1.0, 0.2, 0.2)));
|
||||
|
||||
let box_material = glass;
|
||||
//let box_material = glass;
|
||||
let _ = glass;
|
||||
let _ = metal;
|
||||
let _ = red;
|
||||
@@ -65,6 +66,11 @@ pub fn new(opt: &Opt) -> Scene {
|
||||
10000.,
|
||||
Lambertian::new(ground_color),
|
||||
)),
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(0., 20., -40.),
|
||||
10.,
|
||||
Lambertian::new(ConstantTexture::new(Vec3::new(1., 0.2, 1.))),
|
||||
)),
|
||||
// Blue sphere
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(0., 20., 40.),
|
||||
@@ -84,11 +90,15 @@ pub fn new(opt: &Opt) -> Scene {
|
||||
Lambertian::new(ConstantTexture::new(Vec3::new(1.0, 0.2, 0.2))),
|
||||
)),
|
||||
// STL Mesh
|
||||
Box::new(BVHTriangles::new(&stl_cube, box_material.clone())),
|
||||
Box::new(Translate::new(
|
||||
BVHTriangles::new(&stl_cube, glass),
|
||||
[0., 10., 0.],
|
||||
)),
|
||||
//Box::new(BVHTriangles::new(&stl_cube, box_material.clone())),
|
||||
Box::new(Cuboid::new(
|
||||
[-20., 0., 0.].into(),
|
||||
[0., 20., 20.].into(),
|
||||
Arc::new(box_material),
|
||||
Arc::new(red),
|
||||
)),
|
||||
];
|
||||
let world: Box<dyn Hit> = if opt.use_accel {
|
||||
|
||||
@@ -1,48 +1,12 @@
|
||||
#![allow(clippy::many_single_char_names)]
|
||||
use rand::{self, Rng};
|
||||
|
||||
use crate::{texture::Texture, vec3::Vec3};
|
||||
use crate::{colors::generate_palette, texture::Texture, vec3::Vec3};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Mandelbrot {
|
||||
palette: Vec<Vec3>,
|
||||
}
|
||||
|
||||
// HSV values in [0..1]
|
||||
// returns [r, g, b] values from 0 to 255
|
||||
//From https://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
|
||||
fn hsv_to_rgb(h: f32, s: f32, v: f32) -> Vec3 {
|
||||
let h_i = (h * 6.) as i32;
|
||||
let f = h * 6. - h_i as f32;
|
||||
let p = v * (1. - s);
|
||||
let q = v * (1. - f * s);
|
||||
let t = v * (1. - (1. - f) * s);
|
||||
match h_i {
|
||||
0 => Vec3::new(v, t, p),
|
||||
1 => Vec3::new(q, v, p),
|
||||
2 => Vec3::new(p, v, t),
|
||||
3 => Vec3::new(p, q, v),
|
||||
4 => Vec3::new(t, p, v),
|
||||
5 => Vec3::new(v, p, q),
|
||||
_ => panic!("Unknown H value {}", h_i),
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_palette(num: usize) -> Vec<Vec3> {
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut random = || rng.gen();
|
||||
// use golden ratio
|
||||
let golden_ratio_conjugate = 0.618_034;
|
||||
let mut h = random();
|
||||
(0..num)
|
||||
.map(|_| {
|
||||
h += golden_ratio_conjugate;
|
||||
h %= 1.0;
|
||||
hsv_to_rgb(h, 0.99, 0.99)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
impl Default for Mandelbrot {
|
||||
fn default() -> Self {
|
||||
Mandelbrot {
|
||||
|
||||
@@ -29,6 +29,12 @@ impl Texture for Box<dyn Texture> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Texture for [f32; 3] {
|
||||
fn value(&self, u: f32, v: f32, p: Vec3) -> Vec3 {
|
||||
(*self).into()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user