Initial clumsy parallel renderer.

This commit is contained in:
2018-09-12 15:24:52 -07:00
parent 672dc3cdd2
commit c4e958975c
6 changed files with 210 additions and 40 deletions

View File

@@ -1,11 +1,13 @@
extern crate image;
extern crate rand;
extern crate rayon;
extern crate rtiow;
use std::time::Instant;
use image::RgbImage;
use rand::Rng;
use rayon::prelude::*;
use rtiow::camera::Camera;
use rtiow::hitable::Hit;
@@ -104,15 +106,16 @@ fn random_scene() -> Vec<Box<Hit>> {
objects
}
fn main() -> Result<(), std::io::Error> {
let start = Instant::now();
let mut rng = rand::thread_rng();
// Set to 1 to do full res.
let dev_factor = 4;
let nx = 1200 / dev_factor;
let ny = 800 / dev_factor;
let ns = 100 / dev_factor;
let (cam, world) = if BOOK_COVER {
struct Scene {
world: HitableList,
camera: Camera,
subsamples: usize,
width: usize,
height: usize,
}
fn build_scene(width: usize, height: usize, subsamples: usize) -> Scene {
let (camera, world) = if BOOK_COVER {
let lookfrom = Vec3::new(13., 2., 3.);
let lookat = Vec3::new(0., 0., 0.);
let dist_to_focus = 10.;
@@ -122,7 +125,7 @@ fn main() -> Result<(), std::io::Error> {
lookat,
Vec3::new(0., 1., 0.),
20.,
nx as f32 / ny as f32,
width as f32 / height as f32,
aperture,
dist_to_focus,
);
@@ -138,7 +141,7 @@ fn main() -> Result<(), std::io::Error> {
lookat,
Vec3::new(0., 1., 0.),
20.,
nx as f32 / ny as f32,
width as f32 / height as f32,
aperture,
dist_to_focus,
);
@@ -171,28 +174,60 @@ fn main() -> Result<(), std::io::Error> {
]);
(cam, world)
};
let mut img = RgbImage::new(nx, ny);
for j in 0..ny {
for i in 0..nx {
let mut col: Vec3 = Default::default();
for _ in 0..ns {
let u = (rng.gen_range::<f32>(0., 1.) + i as f32) / nx as f32;
let v = (rng.gen_range::<f32>(0., 1.) + j as f32) / ny as f32;
let r = cam.get_ray(u, v);
col = col + color(r, &world, 0);
}
col = col / ns as f32;
// Gamma correct, use gamma 2 correction, which is 1/gamma where gamma=2 which is 1/2
// or sqrt.
col = Vec3::new(col[0].sqrt(), col[1].sqrt(), col[2].sqrt());
let ir = (255.99 * col[0]) as u8;
let ig = (255.99 * col[1]) as u8;
let ib = (255.99 * col[2]) as u8;
// ny-j is to flip y-axis.
img.put_pixel(i, ny - j - 1, image::Rgb([ir, ig, ib]));
}
Scene {
camera,
world,
subsamples,
width,
height,
}
}
fn trace_pixel(x: usize, y: usize, scene: &Scene) -> [u8; 3] {
let mut rng = rand::thread_rng();
let mut col: Vec3 = Default::default();
for _ in 0..scene.subsamples {
let u = (rng.gen_range::<f32>(0., 1.) + x as f32) / scene.width as f32;
let v = (rng.gen_range::<f32>(0., 1.) + y as f32) / scene.height as f32;
let ray = scene.camera.get_ray(u, v);
col = col + color(ray, &scene.world, 0);
}
col = col / scene.subsamples as f32;
// Gamma correct, use gamma 2 correction, which is 1/gamma where gamma=2 which is 1/2
// or sqrt.
col = Vec3::new(col[0].sqrt(), col[1].sqrt(), col[2].sqrt());
let ir = (255.99 * col[0]) as u8;
let ig = (255.99 * col[1]) as u8;
let ib = (255.99 * col[2]) as u8;
[ir, ig, ib]
}
fn main() -> Result<(), std::io::Error> {
let start = Instant::now();
// Set to 1 to do full res.
let dev_factor = 1;
let width = 1200 / dev_factor;
let height = 800 / dev_factor;
let subsamples = 1000 / dev_factor;
let scene = build_scene(width, height, subsamples);
let mut img = RgbImage::new(width as u32, height as u32);
let coords: Vec<_> = (0..height)
.flat_map(|j| (0..width).map(move |i| (i, j)))
.collect();
let pixels = coords
.par_iter()
.map(|(i, j)| {
let p = trace_pixel(*i, *j, &scene);
// height-j is to flip y-axis.
(*i as u32, (height - *j - 1) as u32, image::Rgb(p))
})
.collect::<Vec<_>>();
pixels
.iter()
.for_each(|(x, y, p)| img.put_pixel(*x, *y, *p));
let runtime = start.elapsed();
eprintln!(
"Render time {}.{} seconds",

View File

@@ -9,6 +9,6 @@ pub struct HitRecord<'m> {
pub material: &'m Material,
}
pub trait Hit: Sync {
pub trait Hit: Send + Sync {
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord>;
}

View File

@@ -28,7 +28,7 @@ pub struct ScatterResponse {
pub reflected: bool,
}
pub trait Material: Sync {
pub trait Material: Send + Sync {
fn scatter(&self, r_in: &Ray, rec: &HitRecord) -> ScatterResponse;
}

View File

@@ -31,21 +31,21 @@ impl Hit for Sphere {
if discriminant > 0. {
let temp = (-b - (b * b - a * c).sqrt()) / a;
if temp < t_max && temp > t_min {
let p = r.point_at_parameter(temp);
let point = r.point_at_parameter(temp);
return Some(HitRecord {
t: temp,
p,
normal: (p - self.center) / self.radius,
p: point,
normal: (point - self.center) / self.radius,
material: &*self.material,
});
}
let temp = (-b + (b * b - a * c).sqrt()) / a;
if temp < t_max && temp > t_min {
let p = r.point_at_parameter(temp);
let point = r.point_at_parameter(temp);
return Some(HitRecord {
t: temp,
p,
normal: (p - self.center) / self.radius,
p: point,
normal: (point - self.center) / self.radius,
material: &*self.material,
});
}