From 62ad8275076aca64a165e803dae0fbf838e2aed5 Mon Sep 17 00:00:00 2001 From: Bill Thiede Date: Fri, 23 Jul 2021 22:12:24 -0700 Subject: [PATCH] eoc9: implement using prelude and builder pattern. --- rtchallenge/examples/eoc9-prelude.rs | 117 +++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 rtchallenge/examples/eoc9-prelude.rs diff --git a/rtchallenge/examples/eoc9-prelude.rs b/rtchallenge/examples/eoc9-prelude.rs new file mode 100644 index 0000000..ccd4542 --- /dev/null +++ b/rtchallenge/examples/eoc9-prelude.rs @@ -0,0 +1,117 @@ +use std::time::Instant; + +use anyhow::Result; +use structopt::StructOpt; + +use rtchallenge::prelude::*; + +use rtchallenge::{camera::RenderStrategy, float::consts::PI, 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(point(-5., 5., -5.)) + .intensity(WHITE) + .build()?; + let light2 = PointLightBuilder::default() + .position(point(5., 5., -5.)) + .intensity([0.2, 0.2, 0.6]) + .build()?; + let light3 = PointLightBuilder::default() + .position(point(0., 2., -5.)) + .intensity([0.2, 0.2, 0.1]) + .build()?; + + let from = point(0., 1.5, -5.); + let to = point(0., 1., 0.); + let up = point(0., 1., 0.); + let camera = CameraBuilder::default() + .hsize(width) + .vsize(height) + .field_of_view(PI / 4.) + .transform(view_transform(from, to, up)) + .render_strategy(opt.render_strategy) + .samples_per_pixel(opt.samples) + .build()?; + + let floor = plane() + .material( + MaterialBuilder::default() + .color([1., 0.2, 0.2]) + .specular(0.) + .build()?, + ) + .build()?; + + let ceiling = plane() + .transform(translation(0., 6., 0.) * rotation_x(PI)) + .material( + MaterialBuilder::default() + .color([0.6, 0.6, 0.8]) + .specular(0.2) + .build()?, + ) + .build()?; + + let middle = sphere() + .transform(translation(-0.5, 0.5, 0.5)) + .material( + MaterialBuilder::default() + .color([0.1, 1., 0.5]) + .diffuse(0.7) + .specular(0.3) + .build()?, + ) + .build()?; + + let right = sphere() + .transform(translation(1.5, 0.5, -0.5) * scaling(0.5, 0.5, 0.5)) + .material( + MaterialBuilder::default() + .color([1., 1., 1.]) + .diffuse(0.7) + .specular(0.0) + .build()?, + ) + .build()?; + + let left = sphere() + .transform(translation(-1.5, 0.33, -0.75) * scaling(0.33, 0.33, 0.33)) + .material( + MaterialBuilder::default() + .color([1., 0.8, 0.1]) + .diffuse(0.7) + .specular(0.3) + .build()?, + ) + .build()?; + + let world = WorldBuilder::default() + .lights(vec![light1, light2, light3]) + .objects(vec![floor, ceiling, middle, right, left]) + .build()?; + + let image = camera.render(&world); + + let path = "/tmp/eoc9.png"; + println!("saving output to {}", path); + image.write_to_file(path)?; + println!("Render time {:.3} seconds", start.elapsed().as_secs_f32()); + Ok(()) +}