#![feature(core_float_math)] mod objects; mod ray; mod vec3; use core::f32; use std::cmp::max; use crate::objects::hit::Hit; use crate::objects::sphere::Sphere; use crate::objects::traits::Hittable; use crate::ray::Ray; use crate::vec3::{Colour, Vec3}; use log::info; use pretty_env_logger; fn ray_colour(hittables: &Vec, r: &Ray) -> Colour { let closest = Hit::hit_list(hittables, r); if let Some(hit) = closest { let n = hit.n(); return 0.5 * Colour::new(n.x() + 1., n.y() + 1., n.z() + 1.); } // background let unit_dir = r.dir().get_unit(); let a = 0.5 * (unit_dir.y() + 1.); (1.0 - a) * Colour::new(1., 1., 1.) + a * Colour::new(0.5, 0.7, 1.0) } fn main() { pretty_env_logger::init(); // setup objects let mut objects = vec![Sphere::new(Vec3::new(0., 0., -1.), 0.5)]; objects.push(Sphere::new(Vec3::new(0., 0., -0.1), 0.01)); objects.push(Sphere::new(Vec3::new(0., -100.5, -1.), 100.)); let aspect_ratio = 16. / 9.; let image_width = 400; let image_height = max(1, (image_width as f32 / aspect_ratio) as u32); //camera let focal_length = 1.; let viewport_height = 2.; let viewport_width = viewport_height * (image_width as f32 / image_height as f32); let camera_center = Vec3::nil(); //viewport let viewport_u = Vec3::new(viewport_width as f32, 0., 0.); let viewport_v = Vec3::new(0., -viewport_height as f32, 0.); let pixel_delta_u = viewport_u / image_width as f32; let pixel_delta_v = viewport_v / image_height as f32; let viewport_upper_left = camera_center - Vec3::new(0., 0., focal_length) - viewport_u / 2 - viewport_v / 2; let pixel00_loc = viewport_upper_left + 0.5 * (pixel_delta_u + pixel_delta_v); let mut imgbuf = image::ImageBuffer::new(image_width, image_height); // render for j in 0..image_height { info!("{}\tScanlines remaining.", (image_height - j)); for i in 0..image_width { let pixel_center = pixel00_loc + (i * pixel_delta_u) + (j * pixel_delta_v); let ray_dir = pixel_center - camera_center; let r = Ray::new(camera_center, ray_dir); let pixel = imgbuf.get_pixel_mut(i, j); *pixel = ray_colour(&objects, &r).output(); } } info!("Writing image file..."); imgbuf.save("output.png").unwrap(); }