Add Mandelbrot texture and test scene.

This commit is contained in:
Bill Thiede 2019-02-19 21:18:37 -08:00
parent c8f5bf9e19
commit 27c1534273
5 changed files with 242 additions and 2 deletions

View File

@ -33,6 +33,7 @@ pub enum Model {
CornellSmoke,
PerlinDebug,
Final,
Mandelbrot,
}
impl Model {
@ -47,6 +48,7 @@ impl Model {
Model::CornellSmoke => scenes::cornell_smoke::new(&opt),
Model::PerlinDebug => scenes::perlin_debug::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),
"perlin_debug" => Ok(Model::PerlinDebug),
"final" => Ok(Model::Final),
"mandelbrot" => Ok(Model::Mandelbrot),
_ => Err(ModelParseError(s.to_owned())),
}
}

View 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,
}
}

View File

@ -4,6 +4,7 @@ pub mod bvh;
pub mod cornell_box;
pub mod cornell_smoke;
pub mod final_scene;
pub mod mandelbrot;
pub mod perlin_debug;
pub mod test;
pub mod tutorial;

View 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()]
}
}

View File

@ -1,12 +1,14 @@
mod checker;
mod constant;
mod image;
mod noise;
mod envmap;
mod image;
mod mandelbrot;
mod noise;
pub use crate::texture::checker::CheckerTexture;
pub use crate::texture::constant::ConstantTexture;
pub use crate::texture::envmap::EnvMap;
pub use crate::texture::image::ImageTexture;
pub use crate::texture::mandelbrot::Mandelbrot;
pub use crate::texture::noise::NoiseTexture;
use std::sync::Arc;