diff --git a/Cargo.lock b/Cargo.lock index e5d0a88..fac14a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -61,6 +61,20 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "console" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89eab4d20ce20cea182308bca13088fecea9c05f6776cf287205d41a0ed3c847" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "terminal_size", + "unicode-width", + "winapi", +] + [[package]] name = "crc32fast" version = "1.3.2" @@ -130,6 +144,12 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "getrandom" version = "0.2.7" @@ -165,6 +185,17 @@ dependencies = [ "png", ] +[[package]] +name = "indicatif" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc42b206e70d86ec03285b123e65a5458c92027d1fb2ae3555878b8113b3ddf" +dependencies = [ + "console", + "number_prefix", + "unicode-width", +] + [[package]] name = "jpeg-decoder" version = "0.2.6" @@ -235,6 +266,12 @@ dependencies = [ "libc", ] +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + [[package]] name = "once_cell" version = "1.13.0" @@ -318,6 +355,7 @@ name = "renderer" version = "0.1.0" dependencies = [ "image", + "indicatif", "rand", "rayon", "tobj", @@ -329,6 +367,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "terminal_size" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "tobj" version = "3.2.3" @@ -338,6 +386,12 @@ dependencies = [ "ahash", ] +[[package]] +name = "unicode-width" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" + [[package]] name = "version_check" version = "0.9.4" @@ -349,3 +403,25 @@ name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index a319adc..3ac7a28 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" [dependencies] image = { version = "0.24.2", default-features = false, features = ["jpeg", "png", "pnm"] } +indicatif = "0.17.0" rand = { version = "0.8.5", features = ["small_rng"] } rayon = "1.5.3" tobj = "3.2.3" diff --git a/src/main.rs b/src/main.rs index 13c4d3a..3cc845e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,11 +13,11 @@ use camera::Camera; use hittable::{HitRecord, Hittable, Sphere, Triangle}; use hittable_list::HittableList; use image::{Rgb, RgbImage}; -use material::{Dielectric, Lambertian, Material, Metal}; +use indicatif::ProgressBar; +use material::{Dielectric, Lambertian, Material, Metal, Rainbow}; use ray::Ray; use rayon::prelude::*; use std::env; -use std::sync::atomic::{AtomicU32, Ordering}; use std::sync::Arc; use tobj; use vec3::{Color, Point3, Vec3}; @@ -170,6 +170,7 @@ fn random_world() -> HittableList { fn from_obj(path: &str) -> HittableList { let mut world = HittableList::new(); + /* let material_ground = Arc::new(Lambertian::new(&Color::new( 29.0 / 255.0, 71.0 / 255.0, @@ -180,14 +181,16 @@ fn from_obj(path: &str) -> HittableList { 5000.0, material_ground.clone(), ))); + */ - let material = Arc::new(Lambertian::new(&Color::new( - 26.0 / 255.0, - 82.0 / 255.0, - 118.0 / 255.0, - ))); + //let material = Arc::new(Lambertian::new(&Color::new( + // 77.0 / 255.0, + // 77.0 / 255.0, + // 118.0 / 255.0, + //))); //let material = Arc::new(Dielectric::new(2.0)); //let material = Arc::new(Metal::new(&Color::new(0.9, 0.9, 0.7), 1.0)); + let material = Arc::new(Rainbow::new()); let cornell_box = tobj::load_obj(path, &tobj::OFFLINE_RENDERING_LOAD_OPTIONS); let (models, materials) = cornell_box.expect("Failed to load OBJ file"); @@ -295,10 +298,10 @@ fn main() { let mut default_file = "image.ppm"; // Image - let aspect_ratio = 16.0 / 9.0; - let image_width = 1200; + let aspect_ratio = 10.0/7.5; //16.0 / 9.0; + let image_width = 1000; let image_height = (image_width as f64 / aspect_ratio) as u32; - let samples_per_pixel = 50_u32; + let samples_per_pixel = 100_u32; let max_depth = 50; let vfov = 40.0; @@ -315,6 +318,7 @@ fn main() { } // World + eprintln!("[1/3] Loading meshes from file..."); let world = from_obj("obj/suzanne.obj"); // let world = random_world(); @@ -335,16 +339,17 @@ fn main() { default_file = &args[1]; } + eprintln!("[2/3] Gerenating image..."); + let bar = ProgressBar::new(image_height as u64); + let mut image = RgbImage::new(image_width, image_height); - let atomic_counter = Arc::new(AtomicU32::new(0)); let color_lines: Vec<_> = (0..image_height) .into_par_iter() // threadded/parallel variant //.into_iter() // iterative variant .rev() .map(|j| { - let v = atomic_counter.fetch_add(1, Ordering::Relaxed); - eprint!("\rScanlines remaining: {:5}", image_height - v); + bar.inc(1); let mut colors = Vec::new(); for i in 0..image_width { @@ -367,8 +372,9 @@ fn main() { return colors; }) .collect(); - eprint!("\rScanlines remaining: {:5}", 0); + bar.finish_and_clear(); + eprintln!("[3/3] Exporting image to disk..."); (0..image_height).into_iter().rev().for_each(|j| { (0..image_width).into_iter().for_each(|i| { color::put_color( @@ -382,5 +388,4 @@ fn main() { }); image.save(default_file).unwrap(); - eprintln!("\nDone!"); } diff --git a/src/material.rs b/src/material.rs index 84b70f5..a8663d8 100644 --- a/src/material.rs +++ b/src/material.rs @@ -17,6 +17,10 @@ pub struct Dielectric { ir: f64, } +pub struct Rainbow { + +} + pub trait Material: Sync + Send { fn scatter( &self, @@ -157,3 +161,34 @@ impl Material for Dielectric { return true; } } + +impl Rainbow { + pub fn new() -> Self { + Rainbow {} + } +} + +impl Material for Rainbow { + fn scatter( + &self, + r_in: &Ray, + rec: &HitRecord, + attenuation: &mut Color, + scattered: &mut Ray, + ) -> bool { + let mut scatter_direction = rec.normal + Vec3::random_unit_vector(); + + if scatter_direction.near_zero() { + scatter_direction = rec.normal; + } + + *scattered = Ray::new(rec.p, scatter_direction); + let color = 0.5*Color::new( + rec.normal.x()+1.0, + rec.normal.y()+1.0, + rec.normal.z()+1.0 + ); + *attenuation = color; + return true; + } +} \ No newline at end of file