camera: protoype supersampling for rayon render pass.

This commit is contained in:
Bill Thiede 2021-07-18 16:31:07 -07:00
parent ce998c68eb
commit 599f484dff
3 changed files with 106 additions and 3 deletions

66
rtchallenge/Cargo.lock generated
View File

@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3
[[package]] [[package]]
name = "addr2line" name = "addr2line"
version = "0.15.2" version = "0.15.2"
@ -306,6 +308,17 @@ dependencies = [
"backtrace", "backtrace",
] ]
[[package]]
name = "getrandom"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]] [[package]]
name = "gimli" name = "gimli"
version = "0.24.0" version = "0.24.0"
@ -508,6 +521,12 @@ dependencies = [
"miniz_oxide 0.3.7", "miniz_oxide 0.3.7",
] ]
[[package]]
name = "ppv-lite86"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]] [[package]]
name = "proc-macro-error" name = "proc-macro-error"
version = "1.0.4" version = "1.0.4"
@ -550,6 +569,46 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "rand"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
"rand_hc",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_hc"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
dependencies = [
"rand_core",
]
[[package]] [[package]]
name = "rayon" name = "rayon"
version = "1.5.1" version = "1.5.1"
@ -606,6 +665,7 @@ dependencies = [
"enum-utils", "enum-utils",
"num_cpus", "num_cpus",
"png", "png",
"rand",
"rayon", "rayon",
"serde", "serde",
"serde_json", "serde_json",
@ -828,6 +888,12 @@ dependencies = [
"winapi-util", "winapi-util",
] ]
[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
version = "0.2.74" version = "0.2.74"

View File

@ -16,6 +16,7 @@ criterion = "0.3.4"
enum-utils = "0.1.2" enum-utils = "0.1.2"
num_cpus = "1.13.0" num_cpus = "1.13.0"
png = "0.16.8" png = "0.16.8"
rand = "0.8.4"
rayon = "1.5.1" rayon = "1.5.1"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.64" serde_json = "1.0.64"

View File

@ -7,6 +7,7 @@ use std::{
thread, thread,
}; };
use rand::Rng;
use rayon::iter::{IntoParallelIterator, ParallelIterator}; use rayon::iter::{IntoParallelIterator, ParallelIterator};
use serde::Deserialize; use serde::Deserialize;
use structopt::StructOpt; use structopt::StructOpt;
@ -114,6 +115,31 @@ impl Camera {
pub fn pixel_size(&self) -> f32 { pub fn pixel_size(&self) -> f32 {
self.pixel_size self.pixel_size
} }
pub fn supersample_rays_for_pixel(&self, px: usize, py: usize, samples: usize) -> Vec<Ray> {
let mut rng = rand::thread_rng();
(0..samples)
.map(|_| {
// The offset from the edge of the canvas to the pixel's corner.
let xoffset = (px as f32 + rng.gen::<f32>()) * self.pixel_size;
let yoffset = (py as f32 + rng.gen::<f32>()) * self.pixel_size;
// The untransformed coordinates of the pixle in world space.
// (Remember that the camera looks toward -z, so +x is to the left.)
let world_x = self.half_width - xoffset;
let world_y = self.half_height - yoffset;
// Using the camera matrix, transofmrm the canvas point and the origin,
// and then compute the ray's direction vector.
// (Remember that the canvas is at z>=-1).
let pixel = self.inverse_transform * Tuple::point(world_x, world_y, -1.);
let origin = self.inverse_transform * Tuple::point(0., 0., 0.);
let direction = (pixel - origin).normalize();
Ray::new(origin, direction)
})
.collect()
}
/// Calculate ray that starts at the camera and passes through the (x,y) /// Calculate ray that starts at the camera and passes through the (x,y)
/// pixel on the canvas. /// pixel on the canvas.
@ -297,9 +323,19 @@ impl Camera {
(0..self.vsize).into_par_iter().for_each(|y| { (0..self.vsize).into_par_iter().for_each(|y| {
let mut row_image = Canvas::new(self.hsize, 1, BLACK); let mut row_image = Canvas::new(self.hsize, 1, BLACK);
for x in 0..self.hsize { for x in 0..self.hsize {
let ray = self.ray_for_pixel(x, y); const SAMPLES: usize = 0;
let color = w.color_at(&ray); if SAMPLES > 0 {
row_image.set(x, 0, color); 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 f32);
} else {
let ray = self.ray_for_pixel(x, y);
let color = w.color_at(&ray);
row_image.set(x, 0, color);
}
} }
// TODO(wathiede): create a row based setter for memcpying the row as a whole. // 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"); let mut image = image_mu.lock().expect("failed to lock image mutex");