176 lines
5.1 KiB
Rust
176 lines
5.1 KiB
Rust
use std::sync::Arc;
|
|
|
|
use image;
|
|
use rand;
|
|
use rand::Rng;
|
|
|
|
use crate::camera::Camera;
|
|
use crate::constant_medium::ConstantMedium;
|
|
use crate::cuboid::Cuboid;
|
|
use crate::hitable::Hit;
|
|
use crate::hitable_list::HitableList;
|
|
use crate::kdtree::KDTree;
|
|
use crate::material::Dielectric;
|
|
use crate::material::DiffuseLight;
|
|
use crate::material::Lambertian;
|
|
use crate::material::Material;
|
|
use crate::material::Metal;
|
|
use crate::moving_sphere::MovingSphere;
|
|
use crate::noise::perlin::Perlin;
|
|
use crate::noise::NoiseType;
|
|
use crate::rect::XZRect;
|
|
use crate::renderer::Opt;
|
|
use crate::renderer::Scene;
|
|
use crate::rotate::RotateY;
|
|
use crate::sphere::Sphere;
|
|
use crate::texture::ConstantTexture;
|
|
use crate::texture::ImageTexture;
|
|
use crate::texture::NoiseTexture;
|
|
use crate::translate::Translate;
|
|
use crate::vec3::Vec3;
|
|
|
|
pub fn new(opt: &Opt) -> Scene {
|
|
let lookfrom = Vec3::new(478., 278., -600.);
|
|
let lookat = Vec3::new(278., 278., 0.);
|
|
let dist_to_focus = 10.;
|
|
let aperture = 0.0;
|
|
let t_min = 0.;
|
|
let t_max = 1.;
|
|
let camera = Camera::new(
|
|
lookfrom,
|
|
lookat,
|
|
Vec3::new(0., 1., 0.),
|
|
40.,
|
|
opt.width as f32 / opt.height as f32,
|
|
aperture,
|
|
dist_to_focus,
|
|
t_min,
|
|
t_max,
|
|
);
|
|
|
|
let nb = 20;
|
|
|
|
let rng = &mut rand::thread_rng();
|
|
let mut boxlist: Vec<Box<Hit>> = Vec::with_capacity(10000);
|
|
let mut list: Vec<Box<Hit>> = Vec::new();
|
|
let white: Arc<Material> = Arc::new(Lambertian::new(ConstantTexture::new([0.73, 0.73, 0.73])));
|
|
let ground: Arc<Material> = Arc::new(Lambertian::new(ConstantTexture::new([0.48, 0.83, 0.53])));
|
|
for i in 0..nb {
|
|
for j in 0..nb {
|
|
let w = 100.;
|
|
let x0 = -1000. + i as f32 * w;
|
|
let z0 = -1000. + j as f32 * w;
|
|
let y0 = 0.;
|
|
let x1 = x0 + w;
|
|
let y1 = 100. * (rng.gen_range::<f32>(0., 1.) + 0.01);
|
|
let z1 = z0 + w;
|
|
boxlist.push(Box::new(Cuboid::new(
|
|
Vec3::new(x0, y0, z0),
|
|
Vec3::new(x1, y1, z1),
|
|
Arc::clone(&ground),
|
|
)));
|
|
}
|
|
}
|
|
list.push(Box::new(KDTree::new(boxlist, t_min, t_max)));
|
|
|
|
let light = DiffuseLight::new(ConstantTexture::new([7., 7., 7.]));
|
|
// Light in ceiling
|
|
list.push(Box::new(XZRect::new(123., 423., 147., 412., 554., light)));
|
|
|
|
let center = Vec3::new(400., 400., 200.);
|
|
// Moving brownish ball
|
|
list.push(Box::new(MovingSphere::new(
|
|
center,
|
|
center + Vec3::new(30., 0., 0.),
|
|
50.,
|
|
t_min,
|
|
t_max,
|
|
Lambertian::new(ConstantTexture::new([0.7, 0.3, 0.1])),
|
|
)));
|
|
|
|
// Glass ball, lower-left corner
|
|
list.push(Box::new(Sphere::new(
|
|
[260., 150., 45.],
|
|
50.,
|
|
Dielectric::new(1.5),
|
|
)));
|
|
// Metal ball lower-right corner
|
|
list.push(Box::new(Sphere::new(
|
|
[0., 150., 145.],
|
|
50.,
|
|
Metal::new([0.8, 0.8, 0.9], 10.0),
|
|
)));
|
|
|
|
// Blue smokey glass ball lower-left
|
|
let boundary: Arc<Hit> = Arc::new(Sphere::new([360., 150., 145.], 70., Dielectric::new(1.5)));
|
|
list.push(Box::new(Arc::clone(&boundary)));
|
|
list.push(Box::new(ConstantMedium::new(
|
|
Arc::clone(&boundary),
|
|
0.2,
|
|
ConstantTexture::new([0.2, 0.4, 0.9]),
|
|
)));
|
|
|
|
// General white mist over whole scene
|
|
let boundary: Arc<Hit> = Arc::new(Sphere::new([0., 0., 0.], 5000., Dielectric::new(1.5)));
|
|
list.push(Box::new(Arc::clone(&boundary)));
|
|
list.push(Box::new(ConstantMedium::new(
|
|
Arc::clone(&boundary),
|
|
0.0001,
|
|
ConstantTexture::new([1.0, 1.0, 1.0]),
|
|
)));
|
|
|
|
// Earth sphere
|
|
let world_image_bytes = include_bytes!("../../images/world.jpg");
|
|
let world = ImageTexture::new(image::load_from_memory(world_image_bytes).unwrap().to_rgb());
|
|
list.push(Box::new(Sphere::new(
|
|
Vec3::new(400., 200., 400.),
|
|
100.,
|
|
Lambertian::new(world),
|
|
)));
|
|
|
|
// Perlin noise sphere
|
|
let noise_source = Perlin::new(rng);
|
|
let noise_type = NoiseType::Marble {
|
|
period: Vec3::new(0., 1., 0.),
|
|
power: 4.,
|
|
size: 32,
|
|
scale: 0.5,
|
|
};
|
|
let pertext = NoiseTexture::new(noise_source, noise_type);
|
|
list.push(Box::new(Sphere::new(
|
|
[220., 280., 300.],
|
|
80.,
|
|
Lambertian::new(pertext),
|
|
)));
|
|
|
|
// White 'cube' made of 1000 spheres
|
|
let ns = 1000;
|
|
let mut boxlist: Vec<Box<Hit>> = Vec::with_capacity(1000);
|
|
for _ in 0..ns {
|
|
boxlist.push(Box::new(Sphere::new(
|
|
[
|
|
165. * rng.gen_range::<f32>(0., 1.),
|
|
165. * rng.gen_range::<f32>(0., 1.),
|
|
165. * rng.gen_range::<f32>(0., 1.),
|
|
],
|
|
10.,
|
|
Arc::clone(&white),
|
|
)));
|
|
}
|
|
list.push(Box::new(Translate::new(
|
|
RotateY::new(KDTree::new(boxlist, t_min, t_max), 15.),
|
|
[-100., 270., 395.],
|
|
)));
|
|
|
|
Scene {
|
|
camera,
|
|
world: Box::new(HitableList::new(list)),
|
|
subsamples: opt.subsamples,
|
|
num_threads: opt.num_threads,
|
|
width: opt.width,
|
|
height: opt.height,
|
|
global_illumination: false,
|
|
env_map: None,
|
|
}
|
|
}
|