diff --git a/Cargo.lock b/Cargo.lock index 359aa4a..b85a7d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,24 +20,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "bit_field" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" - [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bumpalo" -version = "3.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" - [[package]] name = "bytemuck" version = "1.9.1" @@ -71,51 +59,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" -dependencies = [ - "cfg-if", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" -dependencies = [ - "autocfg", - "cfg-if", - "crossbeam-utils", - "lazy_static", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" -dependencies = [ - "cfg-if", - "lazy_static", -] - [[package]] name = "deflate" version = "1.0.0" @@ -125,65 +68,6 @@ dependencies = [ "adler32", ] -[[package]] -name = "either" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" - -[[package]] -name = "exr" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14cc0e06fb5f67e5d6beadf3a382fec9baca1aa751c6d5368fdeee7e5932c215" -dependencies = [ - "bit_field", - "deflate", - "flume", - "half", - "inflate", - "lebe", - "smallvec", - "threadpool", -] - -[[package]] -name = "flate2" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af" -dependencies = [ - "cfg-if", - "crc32fast", - "libc", - "miniz_oxide", -] - -[[package]] -name = "flume" -version = "0.10.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843c03199d0c0ca54bc1ea90ac0d507274c28abcc4f691ae8b4eaa375087c76a" -dependencies = [ - "futures-core", - "futures-sink", - "nanorand", - "pin-project", - "spin", -] - -[[package]] -name = "futures-core" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" - -[[package]] -name = "futures-sink" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" - [[package]] name = "getrandom" version = "0.2.6" @@ -191,35 +75,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" dependencies = [ "cfg-if", - "js-sys", "libc", "wasi", - "wasm-bindgen", -] - -[[package]] -name = "gif" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a7187e78088aead22ceedeee99779455b23fc231fe13ec443f99bb71694e5b" -dependencies = [ - "color_quant", - "weezl", -] - -[[package]] -name = "half" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", ] [[package]] @@ -231,24 +88,11 @@ dependencies = [ "bytemuck", "byteorder", "color_quant", - "exr", - "gif", "jpeg-decoder", "num-iter", "num-rational", "num-traits", "png", - "scoped_threadpool", - "tiff", -] - -[[package]] -name = "inflate" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff" -dependencies = [ - "adler32", ] [[package]] @@ -256,30 +100,6 @@ name = "jpeg-decoder" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be7ef4b99870f0c9f2fc2f20dbef72707e2bcca675bb9196734cf433e999b0c5" -dependencies = [ - "rayon", -] - -[[package]] -name = "js-sys" -version = "0.3.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "lebe" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7efd1d698db0759e6ef11a7cd44407407399a910c774dd804c64c032da7826ff" [[package]] name = "libc" @@ -287,34 +107,6 @@ version = "0.2.125" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b" -[[package]] -name = "lock_api" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg", -] - [[package]] name = "miniz_oxide" version = "0.5.1" @@ -324,15 +116,6 @@ dependencies = [ "adler", ] -[[package]] -name = "nanorand" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" -dependencies = [ - "getrandom", -] - [[package]] name = "num-integer" version = "0.1.45" @@ -374,36 +157,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "pin-project" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "png" version = "0.17.5" @@ -417,45 +170,39 @@ dependencies = [ ] [[package]] -name = "proc-macro2" -version = "1.0.37" +name = "ppv-lite86" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "unicode-xid", + "libc", + "rand_chacha", + "rand_core", ] [[package]] -name = "quote" -version = "1.0.18" +name = "rand_chacha" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ - "proc-macro2", + "ppv-lite86", + "rand_core", ] [[package]] -name = "rayon" -version = "1.5.2" +name = "rand_core" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd249e82c21598a9a426a4e00dd7adc1d640b22445ec8545feef801d1a74c221" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "autocfg", - "crossbeam-deque", - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f51245e1e62e1f1629cbfec37b5793bbabcaeb90f30e94d2ba03564687353e4" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "num_cpus", + "getrandom", ] [[package]] @@ -463,134 +210,11 @@ name = "renderer" version = "0.1.0" dependencies = [ "image", + "rand", ] -[[package]] -name = "scoped_threadpool" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "smallvec" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" - -[[package]] -name = "spin" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c530c2b0d0bf8b69304b39fe2001993e267461948b890cd037d8ad4293fa1a0d" -dependencies = [ - "lock_api", -] - -[[package]] -name = "syn" -version = "1.0.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "threadpool" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" -dependencies = [ - "num_cpus", -] - -[[package]] -name = "tiff" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cfada0986f446a770eca461e8c6566cb879682f7d687c8348aa0c857bd52286" -dependencies = [ - "flate2", - "jpeg-decoder", - "weezl", -] - -[[package]] -name = "unicode-xid" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - -[[package]] -name = "wasm-bindgen" -version = "0.2.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" -dependencies = [ - "bumpalo", - "lazy_static", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" - -[[package]] -name = "weezl" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c97e489d8f836838d497091de568cf16b117486d529ec5579233521065bd5e4" diff --git a/Cargo.toml b/Cargo.toml index c91bb34..e01e985 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,4 +6,5 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -image = "0.24.2" \ No newline at end of file +image = { version = "0.24.2", default-features = false, features = ["jpeg", "png", "pnm"] } +rand = "0.8.5" \ No newline at end of file diff --git a/src/camera.rs b/src/camera.rs new file mode 100644 index 0000000..eea04c0 --- /dev/null +++ b/src/camera.rs @@ -0,0 +1,38 @@ +use super::{Point3, Ray, Vec3}; + +pub struct Camera { + origin: Point3, + lower_left_corner: Point3, + horizontal: Vec3, + vertical: Vec3, +} + +impl Camera { + pub fn new() -> Self { + let aspect_ratio = 16.0 / 9.0; + let viewport_height = 2.0; + let viewport_width = aspect_ratio * viewport_height; + let focal_length = 1.0; + + let origin = Point3::new(0.0, 0.0, 0.0); + let horizontal = Vec3::new(viewport_width, 0.0, 0.0); + let vertical = Vec3::new(0.0, viewport_height, 0.0); + + return Camera { + origin, + horizontal, + vertical, + lower_left_corner: origin + - horizontal / 2.0 + - vertical / 2.0 + - Vec3::new(0.0, 0.0, focal_length), + }; + } + + pub fn get_ray(&self, u: f64, v: f64) -> Ray { + Ray::new( + self.origin, + self.lower_left_corner + u * self.horizontal + v * self.vertical - self.origin, + ) + } +} diff --git a/src/color.rs b/src/color.rs index a9d8bcd..33523e0 100644 --- a/src/color.rs +++ b/src/color.rs @@ -1,4 +1,4 @@ -use super::{Color, Rgb, RgbImage}; +use super::{utility, Color, Rgb, RgbImage}; use std::io::Write; pub fn write_color(out: &mut impl Write, pixel_color: &Color) { @@ -12,9 +12,23 @@ pub fn write_color(out: &mut impl Write, pixel_color: &Color) { .unwrap(); } -pub fn put_color(img: &mut RgbImage, pixel_color: &Color, x: u32, y: u32) { - img.put_pixel(x, y, Rgb( - [(255.999 * pixel_color.x()) as u8, - (255.999 * pixel_color.y()) as u8, - (255.999 * pixel_color.z()) as u8])); +pub fn put_color(img: &mut RgbImage, pixel_color: &Color, x: u32, y: u32, samples_per_pixel: u32) { + let mut r = pixel_color.x(); + let mut g = pixel_color.y(); + let mut b = pixel_color.z(); + + let scale = 1.0 / samples_per_pixel as f64; + r *= scale; + g *= scale; + b *= scale; + + img.put_pixel( + x, + y, + Rgb([ + (256.0 * utility::clamp(r, 0.0, 0.999)) as u8, + (256.0 * utility::clamp(g, 0.0, 0.999)) as u8, + (256.0 * utility::clamp(b, 0.0, 0.999)) as u8, + ]), + ); } diff --git a/src/hittable.rs b/src/hittable.rs index 877b294..430d202 100644 --- a/src/hittable.rs +++ b/src/hittable.rs @@ -24,7 +24,7 @@ impl HitRecord { if self.front_face { self.normal = outward_normal; } else { - self.normal = (-1.0)*outward_normal; + self.normal = (-1.0) * outward_normal; } } @@ -38,7 +38,12 @@ impl HitRecord { } pub fn empty() -> Self { - Self::new(Point3::new(0.0,0.0,0.0), Vec3::new(0.0,0.0,0.0), 0.0, false) + Self::new( + Point3::new(0.0, 0.0, 0.0), + Vec3::new(0.0, 0.0, 0.0), + 0.0, + false, + ) } } diff --git a/src/hittable_list.rs b/src/hittable_list.rs index 05da354..6a877f8 100644 --- a/src/hittable_list.rs +++ b/src/hittable_list.rs @@ -1,15 +1,15 @@ +use super::HitRecord; use super::Hittable; use super::Ray; -use super::HitRecord; pub struct HittableList { objects: Vec>, } impl HittableList { - pub fn new()-> Self { + pub fn new() -> Self { HittableList { - objects: Vec::>::new() + objects: Vec::>::new(), } } @@ -22,7 +22,6 @@ impl HittableList { } pub fn hit(&self, r: &Ray, t_min: f64, t_max: f64, rec: &mut HitRecord) -> bool { - let mut hit_anything = false; let mut closest_so_far = t_max; @@ -37,4 +36,4 @@ impl HittableList { return hit_anything; } -} \ No newline at end of file +} diff --git a/src/main.rs b/src/main.rs index e497ea6..572353c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,34 +1,23 @@ extern crate image; +mod camera; mod color; mod hittable; mod hittable_list; mod ray; -mod vec3; mod utility; +mod vec3; + use std::env; -use std::fs::File; -use std::io::BufWriter; -use std::io::Write; -use vec3::{Color, Point3, Vec3}; -use hittable::{Hittable, Sphere, HitRecord}; +//use std::fs::File; +//use std::io::BufWriter; +//use std::io::Write; +use camera::Camera; +use hittable::{HitRecord, Hittable, Sphere}; use hittable_list::HittableList; +use image::{Rgb, RgbImage}; use ray::Ray; -use image::{ImageBuffer, Rgb, RgbImage}; - -fn hit_sphere(center: &Point3, radius: f64, r: &Ray) -> f64 { - let oc = r.origin() - *center; - let a = r.direction().length_squared(); // gleiches Ergebnis wie Skalarprodukt - let b = 2.0 * Vec3::dot(oc, r.direction()); - let c = oc.length_squared() - radius * radius; - let discriminant = b * b - 4.0 * a * c; - - if discriminant < 0.0 { - return -1.0; - } else { - return (-b - discriminant.sqrt()) / (2.0 * a); - } -} +use vec3::{Color, Point3, Vec3}; fn ray_color(r: &Ray, world: &HittableList) -> Color { let mut rec = HitRecord::empty(); @@ -49,22 +38,41 @@ fn main() { let aspect_ratio = 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; // World let mut world = HittableList::new(); - world.add(Box::::new(Sphere::new(Point3::new(0.0, 0.0, -1.0), 0.5))); - world.add(Box::::new(Sphere::new(Point3::new(0.0, -100.5, -1.0), 100.0))); + world.add(Box::::new(Sphere::new( + Point3::new(0.0, 0.0, -1.0), + 0.5, + ))); + world.add(Box::::new(Sphere::new( + Point3::new(0.0, -100.5, -150.0), + 100.0, + ))); + world.add(Box::::new(Sphere::new( + Point3::new(1.0, 0.0, -1.5), + 0.3, + ))); + world.add(Box::::new(Sphere::new( + Point3::new(1.0, 1.1, -1.5), + 0.3, + ))); + world.add(Box::::new(Sphere::new( + Point3::new(-1.0, 1.1, -1.5), + 0.3, + ))); + + /* + for i in -15..15 { + for j in -15..15 { + world.add(Box::::new(Sphere::new(Point3::new(j as f64/6.0 as f64, i as f64/6.0 as f64, -1.5), 0.05))); + } + } + */ // Camera - let viewport_height = 2.0; - let viewport_width = aspect_ratio * viewport_height; - let focal_length = 1.0; - - let origin = Point3::new(0.0, 0.0, 0.0); - let horizontal = Vec3::new(viewport_width, 0.0, 0.0); - let vertical = Vec3::new(0.0, viewport_height, 0.0); - let lower_left_corner = - origin - horizontal / 2.0 - vertical / 2.0 - Vec3::new(0.0, 0.0, focal_length); + let cam = Camera::new(); // Render let args: Vec = env::args().collect(); @@ -80,17 +88,22 @@ fn main() { for j in (0..image_height).rev() { eprint!("\rScanlines remaining: {j:5}"); for i in 0..image_width { - let u = i as f64 / (image_width - 1) as f64; - let v = j as f64 / (image_height - 1) as f64; - let r = Ray::new( - origin, - lower_left_corner + u * horizontal + v * vertical - origin, - ); - let pixel_color = ray_color(&r, &mut world); + let mut pixel_color = Color::new(0.0, 0.0, 0.0); + for _ in 0..samples_per_pixel { + let u = (i as f64 + utility::random_f64()) / (image_width - 1) as f64; + let v = (j as f64 + utility::random_f64()) / (image_height - 1) as f64; + let r = cam.get_ray(u, v); + pixel_color += ray_color(&r, &mut world); + } //color::write_color(&mut file, &pixel_color); - color::put_color(&mut image, &pixel_color, image_width-i-1, image_height-j-1); - + color::put_color( + &mut image, + &pixel_color, + i, + image_height - j - 1, + samples_per_pixel, + ); } } image.save(default_file).unwrap(); diff --git a/src/utility.rs b/src/utility.rs index e69de29..bbb13a0 100644 --- a/src/utility.rs +++ b/src/utility.rs @@ -0,0 +1,20 @@ +use rand::Rng; + +/// generates random number 0<= x < 1 +pub fn random_f64() -> f64 { + rand::thread_rng().gen_range(0.0..1.0) +} + +pub fn random_rng(min: f64, max: f64) -> f64 { + min + (max - min) * random_f64() +} + +pub fn clamp(x: f64, min: f64, max: f64) -> f64 { + if x < min { + return min; + } + if x > max { + return max; + } + return x; +}