Add Rainbow material based on normal

This commit is contained in:
Jonathan Flueren 2022-08-02 17:07:49 +02:00
parent acbb572dcd
commit c787724541
4 changed files with 132 additions and 15 deletions

76
Cargo.lock generated
View file

@ -61,6 +61,20 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" 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]] [[package]]
name = "crc32fast" name = "crc32fast"
version = "1.3.2" version = "1.3.2"
@ -130,6 +144,12 @@ version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be"
[[package]]
name = "encode_unicode"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.7" version = "0.2.7"
@ -165,6 +185,17 @@ dependencies = [
"png", "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]] [[package]]
name = "jpeg-decoder" name = "jpeg-decoder"
version = "0.2.6" version = "0.2.6"
@ -235,6 +266,12 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "number_prefix"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.13.0" version = "1.13.0"
@ -318,6 +355,7 @@ name = "renderer"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"image", "image",
"indicatif",
"rand", "rand",
"rayon", "rayon",
"tobj", "tobj",
@ -329,6 +367,16 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 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]] [[package]]
name = "tobj" name = "tobj"
version = "3.2.3" version = "3.2.3"
@ -338,6 +386,12 @@ dependencies = [
"ahash", "ahash",
] ]
[[package]]
name = "unicode-width"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]] [[package]]
name = "version_check" name = "version_check"
version = "0.9.4" version = "0.9.4"
@ -349,3 +403,25 @@ name = "wasi"
version = "0.11.0+wasi-snapshot-preview1" version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 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"

View file

@ -7,6 +7,7 @@ edition = "2021"
[dependencies] [dependencies]
image = { version = "0.24.2", default-features = false, features = ["jpeg", "png", "pnm"] } image = { version = "0.24.2", default-features = false, features = ["jpeg", "png", "pnm"] }
indicatif = "0.17.0"
rand = { version = "0.8.5", features = ["small_rng"] } rand = { version = "0.8.5", features = ["small_rng"] }
rayon = "1.5.3" rayon = "1.5.3"
tobj = "3.2.3" tobj = "3.2.3"

View file

@ -13,11 +13,11 @@ use camera::Camera;
use hittable::{HitRecord, Hittable, Sphere, Triangle}; use hittable::{HitRecord, Hittable, Sphere, Triangle};
use hittable_list::HittableList; use hittable_list::HittableList;
use image::{Rgb, RgbImage}; use image::{Rgb, RgbImage};
use material::{Dielectric, Lambertian, Material, Metal}; use indicatif::ProgressBar;
use material::{Dielectric, Lambertian, Material, Metal, Rainbow};
use ray::Ray; use ray::Ray;
use rayon::prelude::*; use rayon::prelude::*;
use std::env; use std::env;
use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Arc; use std::sync::Arc;
use tobj; use tobj;
use vec3::{Color, Point3, Vec3}; use vec3::{Color, Point3, Vec3};
@ -170,6 +170,7 @@ fn random_world() -> HittableList {
fn from_obj(path: &str) -> HittableList { fn from_obj(path: &str) -> HittableList {
let mut world = HittableList::new(); let mut world = HittableList::new();
/*
let material_ground = Arc::new(Lambertian::new(&Color::new( let material_ground = Arc::new(Lambertian::new(&Color::new(
29.0 / 255.0, 29.0 / 255.0,
71.0 / 255.0, 71.0 / 255.0,
@ -180,14 +181,16 @@ fn from_obj(path: &str) -> HittableList {
5000.0, 5000.0,
material_ground.clone(), material_ground.clone(),
))); )));
*/
let material = Arc::new(Lambertian::new(&Color::new( //let material = Arc::new(Lambertian::new(&Color::new(
26.0 / 255.0, // 77.0 / 255.0,
82.0 / 255.0, // 77.0 / 255.0,
118.0 / 255.0, // 118.0 / 255.0,
))); //)));
//let material = Arc::new(Dielectric::new(2.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(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 cornell_box = tobj::load_obj(path, &tobj::OFFLINE_RENDERING_LOAD_OPTIONS);
let (models, materials) = cornell_box.expect("Failed to load OBJ file"); let (models, materials) = cornell_box.expect("Failed to load OBJ file");
@ -295,10 +298,10 @@ fn main() {
let mut default_file = "image.ppm"; let mut default_file = "image.ppm";
// Image // Image
let aspect_ratio = 16.0 / 9.0; let aspect_ratio = 10.0/7.5; //16.0 / 9.0;
let image_width = 1200; let image_width = 1000;
let image_height = (image_width as f64 / aspect_ratio) as u32; 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 max_depth = 50;
let vfov = 40.0; let vfov = 40.0;
@ -315,6 +318,7 @@ fn main() {
} }
// World // World
eprintln!("[1/3] Loading meshes from file...");
let world = from_obj("obj/suzanne.obj"); let world = from_obj("obj/suzanne.obj");
// let world = random_world(); // let world = random_world();
@ -335,16 +339,17 @@ fn main() {
default_file = &args[1]; 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 mut image = RgbImage::new(image_width, image_height);
let atomic_counter = Arc::new(AtomicU32::new(0));
let color_lines: Vec<_> = (0..image_height) let color_lines: Vec<_> = (0..image_height)
.into_par_iter() // threadded/parallel variant .into_par_iter() // threadded/parallel variant
//.into_iter() // iterative variant //.into_iter() // iterative variant
.rev() .rev()
.map(|j| { .map(|j| {
let v = atomic_counter.fetch_add(1, Ordering::Relaxed); bar.inc(1);
eprint!("\rScanlines remaining: {:5}", image_height - v);
let mut colors = Vec::new(); let mut colors = Vec::new();
for i in 0..image_width { for i in 0..image_width {
@ -367,8 +372,9 @@ fn main() {
return colors; return colors;
}) })
.collect(); .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_height).into_iter().rev().for_each(|j| {
(0..image_width).into_iter().for_each(|i| { (0..image_width).into_iter().for_each(|i| {
color::put_color( color::put_color(
@ -382,5 +388,4 @@ fn main() {
}); });
image.save(default_file).unwrap(); image.save(default_file).unwrap();
eprintln!("\nDone!");
} }

View file

@ -17,6 +17,10 @@ pub struct Dielectric {
ir: f64, ir: f64,
} }
pub struct Rainbow {
}
pub trait Material: Sync + Send { pub trait Material: Sync + Send {
fn scatter( fn scatter(
&self, &self,
@ -157,3 +161,34 @@ impl Material for Dielectric {
return true; 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;
}
}