camera: make supersampling configurable, wire it up in eoc8.
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
c4f10126e3
commit
839642b886
@ -22,6 +22,10 @@ use rtchallenge::{
|
||||
struct Opt {
|
||||
#[structopt(long, default_value = "rayon")]
|
||||
render_strategy: RenderStrategy,
|
||||
/// Number of samples per pixel. 0 renders from the center of the pixel, 1 or more samples N
|
||||
/// times randomly across the pixel.
|
||||
#[structopt(short, long, default_value = "0")]
|
||||
samples: usize,
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
@ -38,6 +42,7 @@ fn main() -> Result<()> {
|
||||
let up = Tuple::point(0., 1., 0.);
|
||||
camera.set_transform(view_transform(from, to, up));
|
||||
camera.render_strategy = opt.render_strategy;
|
||||
camera.samples_per_pixel = opt.samples;
|
||||
|
||||
let mut floor = Sphere::default();
|
||||
floor.set_transform(Matrix4x4::scaling(10., 0.01, 10.));
|
||||
|
||||
@ -13,7 +13,12 @@ use serde::Deserialize;
|
||||
use structopt::StructOpt;
|
||||
|
||||
use crate::{
|
||||
canvas::Canvas, matrices::Matrix4x4, rays::Ray, tuples::Tuple, world::World, Float, BLACK,
|
||||
canvas::Canvas,
|
||||
matrices::Matrix4x4,
|
||||
rays::Ray,
|
||||
tuples::{Color, Tuple},
|
||||
world::World,
|
||||
Float, BLACK,
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone, StructOpt, Debug, Deserialize)]
|
||||
@ -41,6 +46,8 @@ pub struct Camera {
|
||||
half_width: Float,
|
||||
half_height: Float,
|
||||
pub render_strategy: RenderStrategy,
|
||||
/// 0 renders from the center of the pixel, 1 or higher is random sampling of the pixel.
|
||||
pub samples_per_pixel: usize,
|
||||
}
|
||||
|
||||
enum Request {
|
||||
@ -94,6 +101,7 @@ impl Camera {
|
||||
half_height,
|
||||
half_width,
|
||||
render_strategy: RenderStrategy::Rayon,
|
||||
samples_per_pixel: 0,
|
||||
}
|
||||
}
|
||||
pub fn hsize(&self) -> usize {
|
||||
@ -275,7 +283,7 @@ impl Camera {
|
||||
let pixel_resp_tx = pixel_resp_tx.clone();
|
||||
thread::spawn(move || {
|
||||
core_affinity::set_for_current(id);
|
||||
render_worker(&c, &w, pixel_req_rx, &pixel_resp_tx);
|
||||
render_worker_task(&c, &w, pixel_req_rx, &pixel_resp_tx);
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
@ -322,19 +330,8 @@ impl Camera {
|
||||
(0..self.vsize).into_par_iter().for_each(|y| {
|
||||
let mut row_image = Canvas::new(self.hsize, 1, BLACK);
|
||||
for x in 0..self.hsize {
|
||||
const SAMPLES: usize = 0;
|
||||
if SAMPLES > 0 {
|
||||
let color = self
|
||||
.supersample_rays_for_pixel(x, y, SAMPLES)
|
||||
.iter()
|
||||
.map(|ray| w.color_at(&ray))
|
||||
.fold(BLACK, |acc, c| acc + c);
|
||||
row_image.set(x, 0, color / SAMPLES as Float);
|
||||
} else {
|
||||
let ray = self.ray_for_pixel(x, y);
|
||||
let color = w.color_at(&ray);
|
||||
row_image.set(x, 0, color);
|
||||
}
|
||||
let color = self.sample(w, x, y);
|
||||
row_image.set(x, 0, color);
|
||||
}
|
||||
// TODO(wathiede): create a row based setter for memcpying the row as a whole.
|
||||
let mut image = image_mu.lock().expect("failed to lock image mutex");
|
||||
@ -352,16 +349,28 @@ impl Camera {
|
||||
let mut image = Canvas::new(self.hsize, self.vsize, BLACK);
|
||||
for y in 0..self.vsize {
|
||||
for x in 0..self.hsize {
|
||||
let ray = self.ray_for_pixel(x, y);
|
||||
let color = w.color_at(&ray);
|
||||
let color = self.sample(w, x, y);
|
||||
image.set(x, y, color);
|
||||
}
|
||||
}
|
||||
image
|
||||
}
|
||||
}
|
||||
|
||||
fn render_worker(
|
||||
fn sample(&self, w: &World, x: usize, y: usize) -> Color {
|
||||
if self.samples_per_pixel > 0 {
|
||||
let color = self
|
||||
.supersample_rays_for_pixel(x, y, self.samples_per_pixel)
|
||||
.iter()
|
||||
.map(|ray| w.color_at(&ray))
|
||||
.fold(BLACK, |acc, c| acc + c);
|
||||
color / self.samples_per_pixel as Float
|
||||
} else {
|
||||
let ray = self.ray_for_pixel(x, y);
|
||||
w.color_at(&ray)
|
||||
}
|
||||
}
|
||||
}
|
||||
fn render_worker_task(
|
||||
c: &Camera,
|
||||
w: &World,
|
||||
input_chan: Arc<Mutex<Receiver<Request>>>,
|
||||
@ -381,8 +390,7 @@ fn render_worker(
|
||||
Request::Line { width, y } => {
|
||||
let mut pixels = Canvas::new(width, 1, BLACK);
|
||||
for x in 0..width {
|
||||
let ray = c.ray_for_pixel(x, y);
|
||||
let color = w.color_at(&ray);
|
||||
let color = c.sample(w, x, y);
|
||||
pixels.set(x, 0, color);
|
||||
}
|
||||
output_chan
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user