balls: experiement with builder pattern.
This commit is contained in:
parent
28fe6fe982
commit
9389fed84c
92
rtchallenge/examples/balls.rs
Normal file
92
rtchallenge/examples/balls.rs
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use structopt::StructOpt;
|
||||||
|
|
||||||
|
use rtchallenge::{
|
||||||
|
camera::{Camera, RenderStrategy},
|
||||||
|
float::consts::PI,
|
||||||
|
lights::PointLightBuilder,
|
||||||
|
materials::MaterialBuilder,
|
||||||
|
matrices::Matrix4x4,
|
||||||
|
shapes::{Geometry, ShapeBuilder},
|
||||||
|
transformations::view_transform,
|
||||||
|
tuples::Tuple,
|
||||||
|
world::WorldBuilder,
|
||||||
|
Float, WHITE,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// End of chapter 9 challenge.
|
||||||
|
#[derive(StructOpt, Debug)]
|
||||||
|
#[structopt(name = "eoc9")]
|
||||||
|
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 light1 = PointLightBuilder::default()
|
||||||
|
.position(Tuple::point(-5., 5., -5.))
|
||||||
|
.intensity(WHITE)
|
||||||
|
.build()?;
|
||||||
|
let light2 = PointLightBuilder::default()
|
||||||
|
.position(Tuple::point(5., 5., -5.))
|
||||||
|
.intensity([0.2, 0.2, 0.6])
|
||||||
|
.build()?;
|
||||||
|
let light3 = PointLightBuilder::default()
|
||||||
|
.position(Tuple::point(0., 2., -5.))
|
||||||
|
.intensity([0.2, 0.2, 0.1])
|
||||||
|
.build()?;
|
||||||
|
|
||||||
|
let from = Tuple::point(0., 1.5, -5.);
|
||||||
|
let to = Tuple::point(0., 1., 0.);
|
||||||
|
let up = Tuple::point(0., 1., 0.);
|
||||||
|
let mut camera = Camera::new(width, height, PI / 4.);
|
||||||
|
camera.set_transform(view_transform(from, to, up));
|
||||||
|
camera.render_strategy = opt.render_strategy;
|
||||||
|
camera.samples_per_pixel = opt.samples;
|
||||||
|
|
||||||
|
let floor = ShapeBuilder::default()
|
||||||
|
.geometry(Geometry::Plane)
|
||||||
|
.material(
|
||||||
|
MaterialBuilder::default()
|
||||||
|
.color([1., 0.2, 0.2])
|
||||||
|
.specular(0.)
|
||||||
|
.build()?,
|
||||||
|
)
|
||||||
|
.build()?;
|
||||||
|
|
||||||
|
const BALL_SIZE: Float = 0.2;
|
||||||
|
let middle = ShapeBuilder::default()
|
||||||
|
.transform(Matrix4x4::scaling(BALL_SIZE, BALL_SIZE, BALL_SIZE))
|
||||||
|
.material(
|
||||||
|
MaterialBuilder::default()
|
||||||
|
.color([0.1, 1., 0.5])
|
||||||
|
.diffuse(0.7)
|
||||||
|
.specular(0.3)
|
||||||
|
.build()?,
|
||||||
|
)
|
||||||
|
.build()?;
|
||||||
|
|
||||||
|
let world = WorldBuilder::default()
|
||||||
|
.lights(vec![light1, light2, light3])
|
||||||
|
.objects(vec![floor, middle])
|
||||||
|
.build()?;
|
||||||
|
|
||||||
|
let image = camera.render(&world);
|
||||||
|
|
||||||
|
let path = "/tmp/balls.png";
|
||||||
|
println!("saving output to {}", path);
|
||||||
|
image.write_to_file(path)?;
|
||||||
|
println!("Render time {:.3} seconds", start.elapsed().as_secs_f32());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user