121 lines
3.7 KiB
Rust
121 lines
3.7 KiB
Rust
use std::time::Instant;
|
|
|
|
use anyhow::Result;
|
|
use structopt::StructOpt;
|
|
|
|
use rtchallenge::{
|
|
camera::{Camera, RenderStrategy},
|
|
float::consts::PI,
|
|
lights::PointLight,
|
|
materials::Material,
|
|
matrices::Matrix4x4,
|
|
spheres::Sphere,
|
|
transformations::view_transform,
|
|
tuples::{Color, Tuple},
|
|
world::World,
|
|
WHITE,
|
|
};
|
|
|
|
/// End of chapter 8 challenge.
|
|
#[derive(StructOpt, Debug)]
|
|
#[structopt(name = "eoc8")]
|
|
struct Opt {
|
|
#[structopt(long, default_value = "rayon")]
|
|
render_strategy: RenderStrategy,
|
|
/// Number of samples per pixel. 0 renders from the center of the pixel, 1 or more samples N
|
|
/// times randomly across the pixel.
|
|
#[structopt(short, long, default_value = "0")]
|
|
samples: usize,
|
|
}
|
|
|
|
fn main() -> Result<()> {
|
|
let start = Instant::now();
|
|
let opt = Opt::from_args();
|
|
let width = 2560;
|
|
let height = 1440;
|
|
|
|
let light_position = Tuple::point(-10., 10., -10.);
|
|
let light_color = WHITE;
|
|
let light1 = PointLight::new(light_position, light_color);
|
|
let light_position = Tuple::point(10., 10., -10.);
|
|
let light_color = Color::new(0.2, 0.2, 0.2);
|
|
let light2 = PointLight::new(light_position, light_color);
|
|
let light_position = Tuple::point(0., 10., -10.);
|
|
let light3 = PointLight::new(light_position, light_color);
|
|
|
|
let mut camera = Camera::new(width, height, PI / 4.);
|
|
let from = Tuple::point(0., 1.5, -5.);
|
|
let to = Tuple::point(0., 1., 0.);
|
|
let up = Tuple::point(0., 1., 0.);
|
|
camera.set_transform(view_transform(from, to, up));
|
|
camera.render_strategy = opt.render_strategy;
|
|
camera.samples_per_pixel = opt.samples;
|
|
|
|
let mut floor = Sphere::default();
|
|
floor.set_transform(Matrix4x4::scaling(10., 0.01, 10.));
|
|
floor.material = Material {
|
|
color: Color::new(1., 0.9, 0.9),
|
|
specular: 0.,
|
|
..Material::default()
|
|
};
|
|
|
|
let mut left_wall = Sphere::default();
|
|
left_wall.set_transform(
|
|
Matrix4x4::translation(0., 0., 5.)
|
|
* Matrix4x4::rotation_y(-PI / 4.)
|
|
* Matrix4x4::rotation_x(PI / 2.)
|
|
* Matrix4x4::scaling(10., 0.01, 10.),
|
|
);
|
|
left_wall.material = floor.material.clone();
|
|
|
|
let mut right_wall = Sphere::default();
|
|
right_wall.set_transform(
|
|
Matrix4x4::translation(0., 0., 5.)
|
|
* Matrix4x4::rotation_y(PI / 4.)
|
|
* Matrix4x4::rotation_x(PI / 2.)
|
|
* Matrix4x4::scaling(10., 0.00001, 10.),
|
|
);
|
|
right_wall.material = floor.material.clone();
|
|
|
|
let mut middle = Sphere::default();
|
|
middle.set_transform(Matrix4x4::translation(-0.5, 1., 0.5));
|
|
middle.material = Material {
|
|
color: Color::new(0.1, 1., 0.5),
|
|
diffuse: 0.7,
|
|
specular: 0.3,
|
|
..Material::default()
|
|
};
|
|
|
|
let mut right = Sphere::default();
|
|
right.set_transform(Matrix4x4::translation(1.5, 0.5, -0.5) * Matrix4x4::scaling(0.5, 0.5, 0.5));
|
|
right.material = Material {
|
|
color: Color::new(1., 1., 1.),
|
|
diffuse: 0.7,
|
|
specular: 0.0,
|
|
..Material::default()
|
|
};
|
|
|
|
let mut left = Sphere::default();
|
|
left.set_transform(
|
|
Matrix4x4::translation(-1.5, 0.33, -0.75) * Matrix4x4::scaling(0.33, 0.33, 0.33),
|
|
);
|
|
left.material = Material {
|
|
color: Color::new(1., 0.8, 0.1),
|
|
diffuse: 0.7,
|
|
specular: 0.3,
|
|
..Material::default()
|
|
};
|
|
|
|
let mut world = World::default();
|
|
world.lights = vec![light1, light2, light3];
|
|
world.objects = vec![floor, left_wall, right_wall, middle, right, left];
|
|
|
|
let image = camera.render(&world);
|
|
|
|
let path = "/tmp/eoc8.png";
|
|
println!("saving output to {}", path);
|
|
image.write_to_file(path)?;
|
|
println!("Render time {:.3} seconds", start.elapsed().as_secs_f32());
|
|
Ok(())
|
|
}
|