Add Mandelbrot texture and test scene.
This commit is contained in:
parent
c8f5bf9e19
commit
27c1534273
@ -33,6 +33,7 @@ pub enum Model {
|
|||||||
CornellSmoke,
|
CornellSmoke,
|
||||||
PerlinDebug,
|
PerlinDebug,
|
||||||
Final,
|
Final,
|
||||||
|
Mandelbrot,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Model {
|
impl Model {
|
||||||
@ -47,6 +48,7 @@ impl Model {
|
|||||||
Model::CornellSmoke => scenes::cornell_smoke::new(&opt),
|
Model::CornellSmoke => scenes::cornell_smoke::new(&opt),
|
||||||
Model::PerlinDebug => scenes::perlin_debug::new(&opt),
|
Model::PerlinDebug => scenes::perlin_debug::new(&opt),
|
||||||
Model::Final => scenes::final_scene::new(&opt),
|
Model::Final => scenes::final_scene::new(&opt),
|
||||||
|
Model::Mandelbrot => scenes::mandelbrot::new(&opt),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,6 +75,7 @@ impl str::FromStr for Model {
|
|||||||
"cornell_smoke" => Ok(Model::CornellSmoke),
|
"cornell_smoke" => Ok(Model::CornellSmoke),
|
||||||
"perlin_debug" => Ok(Model::PerlinDebug),
|
"perlin_debug" => Ok(Model::PerlinDebug),
|
||||||
"final" => Ok(Model::Final),
|
"final" => Ok(Model::Final),
|
||||||
|
"mandelbrot" => Ok(Model::Mandelbrot),
|
||||||
_ => Err(ModelParseError(s.to_owned())),
|
_ => Err(ModelParseError(s.to_owned())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
156
rtiow/src/scenes/mandelbrot.rs
Normal file
156
rtiow/src/scenes/mandelbrot.rs
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
use image;
|
||||||
|
use rand;
|
||||||
|
|
||||||
|
use crate::camera::Camera;
|
||||||
|
use crate::hitable::Hit;
|
||||||
|
use crate::hitable_list::HitableList;
|
||||||
|
use crate::kdtree::KDTree;
|
||||||
|
use crate::material::DiffuseLight;
|
||||||
|
use crate::material::Lambertian;
|
||||||
|
use crate::noise::perlin::Perlin;
|
||||||
|
use crate::noise::NoiseType;
|
||||||
|
use crate::rect::XYRect;
|
||||||
|
use crate::rect::XZRect;
|
||||||
|
use crate::rect::YZRect;
|
||||||
|
use crate::renderer::Opt;
|
||||||
|
use crate::renderer::Scene;
|
||||||
|
use crate::sphere::Sphere;
|
||||||
|
use crate::texture::ConstantTexture;
|
||||||
|
use crate::texture::ImageTexture;
|
||||||
|
use crate::texture::Mandelbrot;
|
||||||
|
use crate::texture::NoiseTexture;
|
||||||
|
use crate::vec3::Vec3;
|
||||||
|
|
||||||
|
pub fn new(opt: &Opt) -> Scene {
|
||||||
|
let lookfrom = Vec3::new(20., 20., 20.);
|
||||||
|
let lookat = Vec3::new(0., 1., 0.);
|
||||||
|
let dist_to_focus = 10.0;
|
||||||
|
let aperture = 0.0;
|
||||||
|
let time_min = 0.;
|
||||||
|
let time_max = 1.;
|
||||||
|
let camera = Camera::new(
|
||||||
|
lookfrom,
|
||||||
|
lookat,
|
||||||
|
Vec3::new(0., 1., 0.),
|
||||||
|
20.,
|
||||||
|
opt.width as f32 / opt.height as f32,
|
||||||
|
aperture,
|
||||||
|
dist_to_focus,
|
||||||
|
time_min,
|
||||||
|
time_max,
|
||||||
|
);
|
||||||
|
let rng = &mut rand::thread_rng();
|
||||||
|
let _ground_color = if opt.use_accel {
|
||||||
|
Box::new(ConstantTexture::new(Vec3::new(1.0, 0.4, 0.4)))
|
||||||
|
} else {
|
||||||
|
Box::new(ConstantTexture::new(Vec3::new(0.4, 1.0, 0.4)))
|
||||||
|
};
|
||||||
|
|
||||||
|
let world_image_bytes = include_bytes!("../../images/world.jpg");
|
||||||
|
let it = ImageTexture::new(image::load_from_memory(world_image_bytes).unwrap().to_rgb());
|
||||||
|
let noise_source = Perlin::new(rng);
|
||||||
|
let noise_type = NoiseType::Scale(10.);
|
||||||
|
let objects: Vec<Box<Hit>> = vec![
|
||||||
|
// Textured globe
|
||||||
|
// Box::new(Sphere::new(Vec3::new(0., 2., 0.), 2.0, Lambertian::new(it))),
|
||||||
|
Box::new(Sphere::new(
|
||||||
|
Vec3::new(0., 2., 0.),
|
||||||
|
2.0,
|
||||||
|
DiffuseLight::new(Mandelbrot::new()),
|
||||||
|
)),
|
||||||
|
// Earth sized sphere
|
||||||
|
Box::new(Sphere::new(
|
||||||
|
Vec3::new(0., -1000., 0.),
|
||||||
|
1000.,
|
||||||
|
// Box::new(Lambertian::new(ground_color)),
|
||||||
|
Lambertian::new(NoiseTexture::new(noise_source, noise_type)),
|
||||||
|
)),
|
||||||
|
Box::new(XZRect::new(
|
||||||
|
-100.,
|
||||||
|
100.,
|
||||||
|
-100.,
|
||||||
|
1000.,
|
||||||
|
60.,
|
||||||
|
DiffuseLight::new(ConstantTexture::new(Vec3::new(1., 1., 1.))),
|
||||||
|
)),
|
||||||
|
Box::new(YZRect::new(
|
||||||
|
1.,
|
||||||
|
3.,
|
||||||
|
-1.,
|
||||||
|
1.,
|
||||||
|
4.,
|
||||||
|
DiffuseLight::new(ConstantTexture::new(Vec3::new(4., 0., 4.))),
|
||||||
|
)),
|
||||||
|
Box::new(YZRect::new(
|
||||||
|
1.,
|
||||||
|
3.,
|
||||||
|
-1.,
|
||||||
|
1.,
|
||||||
|
-4.,
|
||||||
|
DiffuseLight::new(ConstantTexture::new(Vec3::new(0., 4., 0.))),
|
||||||
|
)),
|
||||||
|
Box::new(XZRect::new(
|
||||||
|
-1.,
|
||||||
|
1.,
|
||||||
|
-1.,
|
||||||
|
1.,
|
||||||
|
6.,
|
||||||
|
DiffuseLight::new(ConstantTexture::new(Vec3::new(4., 4., 0.))),
|
||||||
|
)),
|
||||||
|
Box::new(XYRect::new(
|
||||||
|
-1.,
|
||||||
|
1.,
|
||||||
|
1.,
|
||||||
|
3.,
|
||||||
|
-4.,
|
||||||
|
DiffuseLight::new(ConstantTexture::new(Vec3::new(0., 0., 4.))),
|
||||||
|
)),
|
||||||
|
Box::new(XYRect::new(
|
||||||
|
-1.75,
|
||||||
|
1.75,
|
||||||
|
1.,
|
||||||
|
3.,
|
||||||
|
4.,
|
||||||
|
DiffuseLight::new(Mandelbrot::new()),
|
||||||
|
)),
|
||||||
|
/*
|
||||||
|
Box::new(Sphere::new(
|
||||||
|
Vec3::new(0., 0., 0.),
|
||||||
|
0.5,
|
||||||
|
Box::new(Lambertian::new(ConstantTexture::new(Vec3::new(
|
||||||
|
0.1, 0.2, 0.5,
|
||||||
|
)))),
|
||||||
|
)),
|
||||||
|
// Shiny sphere
|
||||||
|
Box::new(Sphere::new(
|
||||||
|
Vec3::new(1., 0., 0.),
|
||||||
|
0.5,
|
||||||
|
Metal::new(Vec3::new(0.8, 0.8, 0.8), 0.2),
|
||||||
|
)),
|
||||||
|
Box::new(MovingSphere::new(
|
||||||
|
Vec3::new(-1., 0., -0.25),
|
||||||
|
Vec3::new(-1., 0., 0.25),
|
||||||
|
0.5,
|
||||||
|
0.,
|
||||||
|
1.,
|
||||||
|
Lambertian::new(ConstantTexture::new(Vec3::new(
|
||||||
|
0.2, 0.8, 0.2,
|
||||||
|
))),
|
||||||
|
)),
|
||||||
|
*/
|
||||||
|
];
|
||||||
|
let world: Box<Hit> = if opt.use_accel {
|
||||||
|
Box::new(KDTree::new(objects, time_min, time_max))
|
||||||
|
} else {
|
||||||
|
Box::new(HitableList::new(objects))
|
||||||
|
};
|
||||||
|
Scene {
|
||||||
|
camera,
|
||||||
|
world,
|
||||||
|
subsamples: opt.subsamples,
|
||||||
|
width: opt.width,
|
||||||
|
height: opt.height,
|
||||||
|
global_illumination: false,
|
||||||
|
env_map: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,6 +4,7 @@ pub mod bvh;
|
|||||||
pub mod cornell_box;
|
pub mod cornell_box;
|
||||||
pub mod cornell_smoke;
|
pub mod cornell_smoke;
|
||||||
pub mod final_scene;
|
pub mod final_scene;
|
||||||
|
pub mod mandelbrot;
|
||||||
pub mod perlin_debug;
|
pub mod perlin_debug;
|
||||||
pub mod test;
|
pub mod test;
|
||||||
pub mod tutorial;
|
pub mod tutorial;
|
||||||
|
|||||||
78
rtiow/src/texture/mandelbrot.rs
Normal file
78
rtiow/src/texture/mandelbrot.rs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
use rand;
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
|
use crate::texture::Texture;
|
||||||
|
use crate::vec3::Vec3;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Mandelbrot {
|
||||||
|
scale: f32,
|
||||||
|
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!(format!("Unknown H value {}", h_i)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_palette(num: usize) -> Vec<Vec3> {
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
let mut random = || rng.gen_range::<f32>(0.0, 0.1);
|
||||||
|
// use golden ratio
|
||||||
|
let golden_ratio_conjugate = 0.618033988749895;
|
||||||
|
let mut h = random();
|
||||||
|
(0..num)
|
||||||
|
.map(|_| {
|
||||||
|
h += golden_ratio_conjugate;
|
||||||
|
h %= 1.0;
|
||||||
|
hsv_to_rgb(h, 0.99, 0.99)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mandelbrot {
|
||||||
|
pub fn new() -> Mandelbrot {
|
||||||
|
Mandelbrot {
|
||||||
|
scale: 2.0,
|
||||||
|
palette: generate_palette(10),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Texture for Mandelbrot {
|
||||||
|
fn value(&self, u: f32, v: f32, _p: Vec3) -> Vec3 {
|
||||||
|
// scaled x coordinate of pixel (scaled to lie in the Mandelbrot X scale (-2.5, 1))
|
||||||
|
let x0 = u * 3.5 - 2.5;
|
||||||
|
// scaled y coordinate of pixel (scaled to lie in the Mandelbrot Y scale (-1, 1))
|
||||||
|
let y0 = v * 2.0 - 1.0;
|
||||||
|
let mut x = 0.0;
|
||||||
|
let mut y = 0.0;
|
||||||
|
let mut iteration = 0;
|
||||||
|
let max_iteration = 1000;
|
||||||
|
while (x * x + y * y) <= 2. * 2. && iteration < max_iteration {
|
||||||
|
let xtemp = x * x - y * y + x0;
|
||||||
|
y = 2. * x * y + y0;
|
||||||
|
x = xtemp;
|
||||||
|
iteration = iteration + 1;
|
||||||
|
}
|
||||||
|
if iteration == max_iteration {
|
||||||
|
return Vec3::default();
|
||||||
|
}
|
||||||
|
self.palette[iteration % self.palette.len()]
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,12 +1,14 @@
|
|||||||
mod checker;
|
mod checker;
|
||||||
mod constant;
|
mod constant;
|
||||||
mod image;
|
|
||||||
mod noise;
|
|
||||||
mod envmap;
|
mod envmap;
|
||||||
|
mod image;
|
||||||
|
mod mandelbrot;
|
||||||
|
mod noise;
|
||||||
pub use crate::texture::checker::CheckerTexture;
|
pub use crate::texture::checker::CheckerTexture;
|
||||||
pub use crate::texture::constant::ConstantTexture;
|
pub use crate::texture::constant::ConstantTexture;
|
||||||
pub use crate::texture::envmap::EnvMap;
|
pub use crate::texture::envmap::EnvMap;
|
||||||
pub use crate::texture::image::ImageTexture;
|
pub use crate::texture::image::ImageTexture;
|
||||||
|
pub use crate::texture::mandelbrot::Mandelbrot;
|
||||||
pub use crate::texture::noise::NoiseTexture;
|
pub use crate::texture::noise::NoiseTexture;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user