use cgmath::prelude::*; use cgmath::{Vector3, vec3}; use rand::prelude::*; use std::f64::consts::PI; mod camera; mod hittable; mod material; mod ray; mod render; mod scene; mod sphere; mod utils; pub fn random_scene(rng: &mut ThreadRng) -> scene::Scene { let mut scene = scene::Scene::new(); scene.add(Box::new(sphere::Sphere::new( vec3(0.0, -1000.0, 0.0), 1000.0, Box::new(material::Lambertian::new(vec3(0.5, 0.5, 0.5)))))); for a in -11 .. 11 { for b in -11 .. 11 { let choose_mat: f64 = rng.gen(); let center = vec3(a as f64 + 0.9*rng.gen::(), 0.2, b as f64 + 0.9*rng.gen::()); if (center - vec3(4.0, 0.2, 0.0)).magnitude() > 0.9 { if choose_mat < 0.8 { // diffuse let albedo = utils::random_vector3(rng, 0.0, 1.0).mul_element_wise(utils::random_vector3(rng, 0.0, 1.0)); scene.add( Box::new(sphere::Sphere::new(center, 0.2, Box::new(material::Lambertian::new(albedo))))); } else if choose_mat < 0.95 { // metal let albedo = utils::random_vector3(rng, 0.5, 1.0); let fuzz = rng.gen_range(0.0, 0.5); scene.add( Box::new(sphere::Sphere::new( center, 0.2, Box::new(material::Metal::new(albedo, fuzz))))); } else { // glass scene.add(Box::new(sphere::Sphere::new( center, 0.2, Box::new(material::Dielectric::new(1.5))))); } } } } scene.add(Box::new(sphere::Sphere::new( vec3(0.0, 1.0, 0.0), 1.0, Box::new(material::Dielectric::new(1.5))))); scene.add( Box::new(sphere::Sphere::new(vec3(-4.0, 1.0, 0.0), 1.0, Box::new(material::Lambertian::new(vec3(0.4, 0.2, 0.1)))))); scene.add( Box::new(sphere::Sphere::new( vec3(4.0, 1.0, 0.0), 1.0, Box::new(material::Metal::new(vec3(0.7, 0.6, 0.5), 0.0))))); scene } fn main() { let image_width = 1200; let image_height = 800; let samples = 100; let max_depth = 50; let aspect_ratio = image_width as f64 / image_height as f64; println!("P3\n{} {}\n255", image_width, image_height); let mut rng = thread_rng(); let scene = random_scene(&mut rng); let lookfrom = vec3(13.0, 2.0, 3.0); let lookat = vec3(0.0, 0.0, 0.0); let vup = vec3(0.0, 1.0, 0.0); let dist_to_focus = 10.0; let aperture = 0.1; let camera = camera::Camera::new(&lookfrom, &lookat, &vup, 20.0 * PI / 180.0, aspect_ratio, aperture, dist_to_focus); render::render(&scene, camera, image_height, image_width, samples, max_depth, &mut rng); eprintln!("\nDone") }