This commit is contained in:
Michael Zhang 2023-01-31 15:07:02 -06:00
parent 0000011089
commit 00000120dd
3 changed files with 132 additions and 29 deletions

View file

@ -17,6 +17,7 @@ dependencies = [
"itertools", "itertools",
"num", "num",
"ordered-float", "ordered-float",
"rayon",
] ]
[[package]] [[package]]
@ -37,6 +38,12 @@ version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.1.4" version = "4.1.4"
@ -74,6 +81,49 @@ dependencies = [
"os_str_bytes", "os_str_bytes",
] ]
[[package]]
name = "crossbeam-channel"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
dependencies = [
"cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
dependencies = [
"cfg-if",
]
[[package]] [[package]]
name = "either" name = "either"
version = "1.8.1" version = "1.8.1"
@ -159,6 +209,15 @@ version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
[[package]]
name = "memoffset"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "num" name = "num"
version = "0.4.0" version = "0.4.0"
@ -238,6 +297,16 @@ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "num_cpus"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
"hermit-abi",
"libc",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.17.0" version = "1.17.0"
@ -301,6 +370,28 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "rayon"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
"num_cpus",
]
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.36.7" version = "0.36.7"
@ -315,6 +406,12 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.152" version = "1.0.152"

View file

@ -11,3 +11,4 @@ clap = { version = "4.1.4", features = ["derive"] }
itertools = "0.10.5" itertools = "0.10.5"
num = { version = "0.4.0", features = ["serde"] } num = { version = "0.4.0", features = ["serde"] }
ordered-float = "3.4.0" ordered-float = "3.4.0"
rayon = "1.6.1"

View file

@ -15,8 +15,9 @@ use anyhow::Result;
use clap::Parser; use clap::Parser;
use itertools::Itertools; use itertools::Itertools;
use ordered_float::NotNan; use ordered_float::NotNan;
use rayon::prelude::{IntoParallelIterator, ParallelIterator};
use crate::image::{Image, Pixel}; use crate::image::Image;
use crate::input_file::parse_input_file; use crate::input_file::parse_input_file;
use crate::ray::Ray; use crate::ray::Ray;
use crate::scene_data::Object; use crate::scene_data::Object;
@ -98,40 +99,44 @@ fn main() -> Result<()> {
} }
}; };
// This is an L because par_bridge is unordered
let pixels = (0..scene.image_width)
.cartesian_product(0..scene.image_height)
.collect_vec();
// Loop through every single pixel of the output file // Loop through every single pixel of the output file
let mut pixels = let pixels = pixels
vec![Pixel::default(); scene.image_width * scene.image_width]; .into_par_iter()
for (px, py) in .map(|(px, py)| {
(0..scene.image_width).cartesian_product(0..scene.image_height) let pixel_in_space = pixel_translation(px, py);
{ let ray = Ray::from_endpoints(scene.eye_pos, pixel_in_space);
let pixel_in_space = pixel_translation(px, py);
let ray = Ray::from_endpoints(scene.eye_pos, pixel_in_space);
let earliest_intersection = scene let earliest_intersection = scene
.objects .objects
.iter() .iter()
.filter_map(|object| { .filter_map(|object| {
let sphere = match object { let sphere = match object {
Object::Sphere(v) => v, Object::Sphere(v) => v,
_ => return None, /* TODO: Handle other object types for _ => return None, /* TODO: Handle other object types for
* intersection as well */ * intersection as well */
}; };
ray.intersects_at(sphere).map(|t| (t, sphere)) ray.intersects_at(sphere).map(|t| (t, sphere))
}) })
.min_by_key(|(t, _)| NotNan::new(*t).unwrap()); .min_by_key(|(t, _)| NotNan::new(*t).unwrap());
let pixel_color = match earliest_intersection { let pixel_color = match earliest_intersection {
Some((_, sphere)) => scene.material_colors[sphere.material], Some((_, sphere)) => scene.material_colors[sphere.material],
// There was no intersection, so this should default to the background // There was no intersection, so this should default to the background
// color // color
None => scene.bkg_color, None => scene.bkg_color,
}; };
// println!("({px}, {py}): {intersection:?}\t{ray:?} {sphere:?}"); // println!("({px}, {py}): {intersection:?}\t{ray:?} {sphere:?}");
pixels[py * scene.image_height + px] = pixel_color.to_pixel(); pixel_color.to_pixel()
} })
.collect::<Vec<_>>();
let image = Image { let image = Image {
width: scene.image_width, width: scene.image_width,