Created
October 19, 2016 00:10
-
-
Save jamwt/e446e220d2cd87c9dffbe939a0f59705 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/rust/Cargo.toml b/rust/Cargo.toml | |
index b24d5cf..c715446 100644 | |
--- a/rust/Cargo.toml | |
+++ b/rust/Cargo.toml | |
@@ -6,4 +6,6 @@ authors = [ "David Shoemaker <[email protected]>" ] | |
[dependencies] | |
image = "*" | |
+itertools = "*" | |
+rayon = "*" | |
regex = "*" | |
diff --git a/rust/src/buffer.rs b/rust/src/buffer.rs | |
new file mode 100644 | |
index 0000000..3bf0c78 | |
--- /dev/null | |
+++ b/rust/src/buffer.rs | |
@@ -0,0 +1,33 @@ | |
+use std::cell::UnsafeCell; | |
+ | |
+pub struct ParallelPixelBuffer { | |
+ width: u32, | |
+ contents: UnsafeCell<Vec<u8>>, | |
+} | |
+ | |
+unsafe impl Sync for ParallelPixelBuffer {} | |
+ | |
+impl ParallelPixelBuffer { | |
+ pub fn new(width: u32, height: u32) -> ParallelPixelBuffer { | |
+ ParallelPixelBuffer { | |
+ width: width, | |
+ contents: UnsafeCell::new(vec![0u8; (width * height * 3) as usize]), | |
+ } | |
+ } | |
+ | |
+ pub fn put_pixel(&self, l: u32, t: u32, x: u8, y: u8, z: u8) { | |
+ unsafe { | |
+ let contents = &mut *self.contents.get(); | |
+ let base = (((t * self.width) + l) * 3) as usize; | |
+ *contents.get_unchecked_mut(base) = x; | |
+ *contents.get_unchecked_mut(base + 1) = y; | |
+ *contents.get_unchecked_mut(base + 2) = z; | |
+ } | |
+ } | |
+ | |
+ pub fn into_inner(self) -> Vec<u8> { | |
+ unsafe { | |
+ self.contents.into_inner() | |
+ } | |
+ } | |
+} | |
diff --git a/rust/src/main.rs b/rust/src/main.rs | |
index 7c60dfc..0f32c14 100644 | |
--- a/rust/src/main.rs | |
+++ b/rust/src/main.rs | |
@@ -1,4 +1,6 @@ | |
extern crate image; | |
+#[macro_use] extern crate itertools; | |
+extern crate rayon; | |
extern crate regex; | |
use std::fs::File; | |
@@ -7,6 +9,7 @@ use std::io::Read; | |
use std::path::Path; | |
use std::env; | |
+mod buffer; | |
mod vector; | |
mod ray; | |
mod camera; | |
diff --git a/rust/src/scene.rs b/rust/src/scene.rs | |
index 3d21d15..30d89d9 100644 | |
--- a/rust/src/scene.rs | |
+++ b/rust/src/scene.rs | |
@@ -1,3 +1,4 @@ | |
+use buffer::ParallelPixelBuffer; | |
use camera::Camera; | |
use vector::Vector3; | |
use ray::{ Ray, HitInfo }; | |
@@ -6,6 +7,7 @@ use image::{ ImageBuffer, Rgb }; | |
use sceneobject::SceneObject; | |
use light::Light; | |
use material::Material; | |
+use rayon::prelude::*; | |
#[derive(Debug)] | |
pub struct Scene { | |
@@ -41,7 +43,13 @@ impl Scene { | |
} | |
pub fn raytrace(&self) -> ImageBuffer<Rgb<u8>, Vec<u8>> { | |
- ImageBuffer::from_fn(self.width, self.height, |x, y| { | |
+ // TODO(jamwt) -- we don't have to actually collect this | |
+ // if we implement IntoParallelIterator on our pixel buffer. | |
+ let coords: Vec<_> = iproduct!(0..self.width, 0..self.height).collect(); | |
+ | |
+ // Now let's do the pixels in parallel. | |
+ let pixels = ParallelPixelBuffer::new(self.width, self.height); | |
+ coords.par_iter().for_each(|&(x, y)| { | |
let eye_ray = self.camera.eye_ray(x, y); | |
let color = if let Some(hit) = self.trace(&eye_ray, 0.001, f64::MAX) { | |
self.shade(&hit, &eye_ray, 0) * 255.0 | |
@@ -49,8 +57,10 @@ impl Scene { | |
else { | |
self.bgcolor * 255.0 | |
}; | |
- Rgb([color.x as u8, color.y as u8, color.z as u8]) | |
- }) | |
+ pixels.put_pixel(x, y, color.x as u8, color.y as u8, color.z as u8); | |
+ }); | |
+ ImageBuffer::from_raw(self.width, self.height, pixels.into_inner()) | |
+ .expect("Buffer not big enough??") | |
} | |
fn trace(&self, ray: &Ray, min: f64, max: f64) -> Option<HitInfo> { | |
diff --git a/rust/src/sceneobject.rs b/rust/src/sceneobject.rs | |
index e6bd88d..432e1c5 100644 | |
--- a/rust/src/sceneobject.rs | |
+++ b/rust/src/sceneobject.rs | |
@@ -1,6 +1,6 @@ | |
use ray::{ Ray, HitInfo }; | |
use std::fmt::Debug; | |
-pub trait SceneObject: Debug { | |
+pub trait SceneObject: Debug + Sync { | |
fn intersect(&self, ray: &Ray, min: f64, max: f64) -> Option<HitInfo>; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment