Compare commits
No commits in common. "7f28a321e32b76dc2aad28f37c9ef81af71f8505" and "235a9d12043be5da7618c7c0dfe9566eab34a869" have entirely different histories.
7f28a321e3
...
235a9d1204
1
rtiow/Cargo.lock
generated
1
rtiow/Cargo.lock
generated
@ -1606,6 +1606,7 @@ dependencies = [
|
|||||||
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cpuprofiler 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cpuprofiler 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"criterion 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"image 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"image 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|||||||
@ -13,6 +13,7 @@ actix-web = "0.7.8"
|
|||||||
askama = "0.7.1"
|
askama = "0.7.1"
|
||||||
chrono = "*"
|
chrono = "*"
|
||||||
cpuprofiler = { version = "0.0.3", optional = true }
|
cpuprofiler = { version = "0.0.3", optional = true }
|
||||||
|
crossbeam-channel = "0.3"
|
||||||
image = "0.19.0"
|
image = "0.19.0"
|
||||||
lazy_static = "1.1.0"
|
lazy_static = "1.1.0"
|
||||||
log = "0.4.5"
|
log = "0.4.5"
|
||||||
|
|||||||
@ -12,7 +12,7 @@ use crate::hitable::HitRecord;
|
|||||||
use crate::ray::Ray;
|
use crate::ray::Ray;
|
||||||
|
|
||||||
enum BVHNode {
|
enum BVHNode {
|
||||||
Leaf(Box<dyn Hit>),
|
Leaf(Box<Hit>),
|
||||||
Branch {
|
Branch {
|
||||||
left: Box<BVHNode>,
|
left: Box<BVHNode>,
|
||||||
right: Box<BVHNode>,
|
right: Box<BVHNode>,
|
||||||
@ -43,7 +43,7 @@ impl fmt::Display for BVHNode {
|
|||||||
|
|
||||||
// Lint is wrong when dealing with Box<Trait>
|
// Lint is wrong when dealing with Box<Trait>
|
||||||
#[allow(clippy::borrowed_box)]
|
#[allow(clippy::borrowed_box)]
|
||||||
fn box_x_compare(ah: &Box<dyn Hit>, bh: &Box<dyn Hit>) -> std::cmp::Ordering {
|
fn box_x_compare(ah: &Box<Hit>, bh: &Box<Hit>) -> std::cmp::Ordering {
|
||||||
match (ah.bounding_box(0., 0.), bh.bounding_box(0., 0.)) {
|
match (ah.bounding_box(0., 0.), bh.bounding_box(0., 0.)) {
|
||||||
(Some(box_left), Some(box_right)) => {
|
(Some(box_left), Some(box_right)) => {
|
||||||
box_left.min().x.partial_cmp(&box_right.min().x).unwrap()
|
box_left.min().x.partial_cmp(&box_right.min().x).unwrap()
|
||||||
@ -53,7 +53,7 @@ fn box_x_compare(ah: &Box<dyn Hit>, bh: &Box<dyn Hit>) -> std::cmp::Ordering {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::borrowed_box)]
|
#[allow(clippy::borrowed_box)]
|
||||||
fn box_y_compare(ah: &Box<dyn Hit>, bh: &Box<dyn Hit>) -> std::cmp::Ordering {
|
fn box_y_compare(ah: &Box<Hit>, bh: &Box<Hit>) -> std::cmp::Ordering {
|
||||||
match (ah.bounding_box(0., 0.), bh.bounding_box(0., 0.)) {
|
match (ah.bounding_box(0., 0.), bh.bounding_box(0., 0.)) {
|
||||||
(Some(box_left), Some(box_right)) => {
|
(Some(box_left), Some(box_right)) => {
|
||||||
box_left.min().y.partial_cmp(&box_right.min().y).unwrap()
|
box_left.min().y.partial_cmp(&box_right.min().y).unwrap()
|
||||||
@ -63,7 +63,7 @@ fn box_y_compare(ah: &Box<dyn Hit>, bh: &Box<dyn Hit>) -> std::cmp::Ordering {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::borrowed_box)]
|
#[allow(clippy::borrowed_box)]
|
||||||
fn box_z_compare(ah: &Box<dyn Hit>, bh: &Box<dyn Hit>) -> std::cmp::Ordering {
|
fn box_z_compare(ah: &Box<Hit>, bh: &Box<Hit>) -> std::cmp::Ordering {
|
||||||
match (ah.bounding_box(0., 0.), bh.bounding_box(0., 0.)) {
|
match (ah.bounding_box(0., 0.), bh.bounding_box(0., 0.)) {
|
||||||
(Some(box_left), Some(box_right)) => {
|
(Some(box_left), Some(box_right)) => {
|
||||||
box_left.min().z.partial_cmp(&box_right.min().z).unwrap()
|
box_left.min().z.partial_cmp(&box_right.min().z).unwrap()
|
||||||
@ -99,11 +99,11 @@ fn vec_split_into<T>(v: Vec<T>, offset: usize) -> (Vec<T>, Vec<T>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BVHNode {
|
impl BVHNode {
|
||||||
fn new(l: Vec<Box<dyn Hit>>, t_min: f32, t_max: f32) -> BVHNode {
|
fn new(l: Vec<Box<Hit>>, t_min: f32, t_max: f32) -> BVHNode {
|
||||||
if l.len() == 1 {
|
if l.len() == 1 {
|
||||||
BVHNode::Leaf(vec_first_into(l))
|
BVHNode::Leaf(vec_first_into(l))
|
||||||
} else {
|
} else {
|
||||||
let mut l: Vec<Box<dyn Hit>> = l.into_iter().collect();
|
let mut l: Vec<Box<Hit>> = l.into_iter().collect();
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
match rng.gen_range::<u16>(0, 3) {
|
match rng.gen_range::<u16>(0, 3) {
|
||||||
0 => l.sort_by(box_x_compare),
|
0 => l.sort_by(box_x_compare),
|
||||||
@ -121,7 +121,7 @@ impl BVHNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn surrounding_box(left: &dyn Hit, right: &dyn Hit, t_min: f32, t_max: f32) -> Option<AABB> {
|
fn surrounding_box(left: &Hit, right: &Hit, t_min: f32, t_max: f32) -> Option<AABB> {
|
||||||
match (
|
match (
|
||||||
left.bounding_box(t_min, t_max),
|
left.bounding_box(t_min, t_max),
|
||||||
right.bounding_box(t_min, t_max),
|
right.bounding_box(t_min, t_max),
|
||||||
@ -185,7 +185,7 @@ pub struct BVH {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BVH {
|
impl BVH {
|
||||||
pub fn new(l: Vec<Box<dyn Hit>>, t_min: f32, t_max: f32) -> BVH {
|
pub fn new(l: Vec<Box<Hit>>, t_min: f32, t_max: f32) -> BVH {
|
||||||
let count = l.len();
|
let count = l.len();
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
let bvh = BVH {
|
let bvh = BVH {
|
||||||
|
|||||||
@ -21,7 +21,7 @@ pub struct Cuboid {
|
|||||||
impl Cuboid {
|
impl Cuboid {
|
||||||
// This clippy doesn't work right with Arc.
|
// This clippy doesn't work right with Arc.
|
||||||
#[allow(clippy::needless_pass_by_value)]
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
pub fn new(p_min: Vec3, p_max: Vec3, material: Arc<dyn Material>) -> Cuboid {
|
pub fn new(p_min: Vec3, p_max: Vec3, material: Arc<Material>) -> Cuboid {
|
||||||
Cuboid {
|
Cuboid {
|
||||||
p_min,
|
p_min,
|
||||||
p_max,
|
p_max,
|
||||||
|
|||||||
@ -10,7 +10,7 @@ pub struct HitRecord<'m> {
|
|||||||
pub uv: (f32, f32),
|
pub uv: (f32, f32),
|
||||||
pub p: Vec3,
|
pub p: Vec3,
|
||||||
pub normal: Vec3,
|
pub normal: Vec3,
|
||||||
pub material: &'m dyn Material,
|
pub material: &'m Material,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Hit: Send + Sync {
|
pub trait Hit: Send + Sync {
|
||||||
@ -18,7 +18,7 @@ pub trait Hit: Send + Sync {
|
|||||||
fn bounding_box(&self, t_min: f32, t_max: f32) -> Option<AABB>;
|
fn bounding_box(&self, t_min: f32, t_max: f32) -> Option<AABB>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hit for Arc<dyn Hit> {
|
impl Hit for Arc<Hit> {
|
||||||
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord> {
|
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord> {
|
||||||
(**self).hit(r, t_min, t_max)
|
(**self).hit(r, t_min, t_max)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,11 +9,11 @@ use crate::vec3::Vec3;
|
|||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct HitableList {
|
pub struct HitableList {
|
||||||
list: Vec<Box<dyn Hit>>,
|
list: Vec<Box<Hit>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HitableList {
|
impl HitableList {
|
||||||
pub fn new(list: Vec<Box<dyn Hit>>) -> HitableList {
|
pub fn new(list: Vec<Box<Hit>>) -> HitableList {
|
||||||
HitableList { list }
|
HitableList { list }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ use crate::hitable::HitRecord;
|
|||||||
use crate::ray::Ray;
|
use crate::ray::Ray;
|
||||||
|
|
||||||
pub enum KDTree {
|
pub enum KDTree {
|
||||||
Leaf(Box<dyn Hit>),
|
Leaf(Box<Hit>),
|
||||||
Branch {
|
Branch {
|
||||||
left: Box<KDTree>,
|
left: Box<KDTree>,
|
||||||
right: Box<KDTree>,
|
right: Box<KDTree>,
|
||||||
@ -42,7 +42,7 @@ fn vec_split_into<T>(v: Vec<T>, offset: usize) -> (Vec<T>, Vec<T>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl KDTree {
|
impl KDTree {
|
||||||
pub fn new(l: Vec<Box<dyn Hit>>, t_min: f32, t_max: f32) -> KDTree {
|
pub fn new(l: Vec<Box<Hit>>, t_min: f32, t_max: f32) -> KDTree {
|
||||||
if l.is_empty() {
|
if l.is_empty() {
|
||||||
panic!("Attempt to build k-d tree with no Hit objects");
|
panic!("Attempt to build k-d tree with no Hit objects");
|
||||||
}
|
}
|
||||||
@ -150,11 +150,9 @@ impl fmt::Display for KDTree {
|
|||||||
impl Hit for KDTree {
|
impl Hit for KDTree {
|
||||||
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord> {
|
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord> {
|
||||||
match self.bounding_box(t_min, t_max) {
|
match self.bounding_box(t_min, t_max) {
|
||||||
Some(bbox) => {
|
Some(bbox) => if !bbox.hit(r, t_min, t_max) {
|
||||||
if !bbox.hit(r, t_min, t_max) {
|
return None;
|
||||||
return None;
|
},
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
None => {
|
||||||
info!("KDTree::hit no bbox: {:?}", r);
|
info!("KDTree::hit no bbox: {:?}", r);
|
||||||
return None;
|
return None;
|
||||||
@ -165,13 +163,11 @@ impl Hit for KDTree {
|
|||||||
KDTree::Branch { left, right, bbox } => match bbox {
|
KDTree::Branch { left, right, bbox } => match bbox {
|
||||||
None => None,
|
None => None,
|
||||||
Some(_bbox) => match (left.hit(r, t_min, t_max), right.hit(r, t_min, t_max)) {
|
Some(_bbox) => match (left.hit(r, t_min, t_max), right.hit(r, t_min, t_max)) {
|
||||||
(Some(hit_left), Some(hit_right)) => {
|
(Some(hit_left), Some(hit_right)) => if hit_left.t < hit_right.t {
|
||||||
if hit_left.t < hit_right.t {
|
Some(hit_left)
|
||||||
Some(hit_left)
|
} else {
|
||||||
} else {
|
Some(hit_right)
|
||||||
Some(hit_right)
|
},
|
||||||
}
|
|
||||||
}
|
|
||||||
(Some(hit_left), None) => Some(hit_left),
|
(Some(hit_left), None) => Some(hit_left),
|
||||||
(None, Some(hit_right)) => Some(hit_right),
|
(None, Some(hit_right)) => Some(hit_right),
|
||||||
(None, None) => None,
|
(None, None) => None,
|
||||||
|
|||||||
@ -20,6 +20,7 @@ pub mod texture;
|
|||||||
pub mod translate;
|
pub mod translate;
|
||||||
pub mod vec3;
|
pub mod vec3;
|
||||||
|
|
||||||
|
extern crate crossbeam_channel;
|
||||||
extern crate image;
|
extern crate image;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|||||||
@ -13,12 +13,11 @@ fn random_in_unit_sphere() -> Vec3 {
|
|||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
let v = Vec3::new(1., 1., 1.);
|
let v = Vec3::new(1., 1., 1.);
|
||||||
loop {
|
loop {
|
||||||
let p =
|
let p = 2. * Vec3::new(
|
||||||
2. * Vec3::new(
|
rng.gen_range::<f32>(0., 1.),
|
||||||
rng.gen_range::<f32>(0., 1.),
|
rng.gen_range::<f32>(0., 1.),
|
||||||
rng.gen_range::<f32>(0., 1.),
|
rng.gen_range::<f32>(0., 1.),
|
||||||
rng.gen_range::<f32>(0., 1.),
|
) - v;
|
||||||
) - v;
|
|
||||||
if p.squared_length() < 1. {
|
if p.squared_length() < 1. {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@ -39,7 +38,7 @@ pub trait Material: Send + Sync {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Material for Arc<dyn Material> {
|
impl Material for Arc<Material> {
|
||||||
fn scatter(&self, r_in: &Ray, rec: &HitRecord) -> ScatterResponse {
|
fn scatter(&self, r_in: &Ray, rec: &HitRecord) -> ScatterResponse {
|
||||||
(**self).scatter(r_in, rec)
|
(**self).scatter(r_in, rec)
|
||||||
}
|
}
|
||||||
@ -48,7 +47,7 @@ impl Material for Arc<dyn Material> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Material for Box<dyn Material> {
|
impl Material for Box<Material> {
|
||||||
fn scatter(&self, r_in: &Ray, rec: &HitRecord) -> ScatterResponse {
|
fn scatter(&self, r_in: &Ray, rec: &HitRecord) -> ScatterResponse {
|
||||||
(**self).scatter(r_in, rec)
|
(**self).scatter(r_in, rec)
|
||||||
}
|
}
|
||||||
@ -258,7 +257,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn arc_material() {
|
fn arc_material() {
|
||||||
let white: Arc<dyn Material> =
|
let white: Arc<Material> =
|
||||||
Arc::new(Lambertian::new(ConstantTexture::new([0.73, 0.73, 0.73])));
|
Arc::new(Lambertian::new(ConstantTexture::new([0.73, 0.73, 0.73])));
|
||||||
|
|
||||||
fn material_fn<M>(m: M)
|
fn material_fn<M>(m: M)
|
||||||
|
|||||||
@ -38,7 +38,7 @@ pub trait NoiseSource: Send + Sync {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NoiseSource for Box<dyn NoiseSource> {
|
impl NoiseSource for Box<NoiseSource> {
|
||||||
fn value(&self, p: Vec3) -> f32 {
|
fn value(&self, p: Vec3) -> f32 {
|
||||||
(**self).value(p)
|
(**self).value(p)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,13 +6,9 @@ use std::path::Path;
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::sync;
|
use std::sync;
|
||||||
use std::sync::mpsc::sync_channel;
|
|
||||||
use std::sync::mpsc::Receiver;
|
|
||||||
use std::sync::mpsc::SyncSender;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use std::sync::Mutex;
|
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
|
use crossbeam_channel as channel;
|
||||||
use image;
|
use image;
|
||||||
use image::RgbImage;
|
use image::RgbImage;
|
||||||
use num_cpus;
|
use num_cpus;
|
||||||
@ -160,7 +156,7 @@ pub fn opt_hash(opt: &Opt) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Scene {
|
pub struct Scene {
|
||||||
pub world: Box<dyn Hit>,
|
pub world: Box<Hit>,
|
||||||
pub camera: Camera,
|
pub camera: Camera,
|
||||||
pub subsamples: usize,
|
pub subsamples: usize,
|
||||||
pub num_threads: Option<usize>,
|
pub num_threads: Option<usize>,
|
||||||
@ -175,7 +171,7 @@ pub struct Scene {
|
|||||||
// world. If false, it is expected the scene has emissive light sources.
|
// world. If false, it is expected the scene has emissive light sources.
|
||||||
fn color(
|
fn color(
|
||||||
r: Ray,
|
r: Ray,
|
||||||
world: &dyn Hit,
|
world: &Hit,
|
||||||
depth: usize,
|
depth: usize,
|
||||||
global_illumination: bool,
|
global_illumination: bool,
|
||||||
env_map: &Option<EnvMap>,
|
env_map: &Option<EnvMap>,
|
||||||
@ -259,25 +255,19 @@ fn render_pixel(scene: &Scene, x: usize, y: usize) -> Vec3 {
|
|||||||
fn render_worker(
|
fn render_worker(
|
||||||
tid: usize,
|
tid: usize,
|
||||||
scene: &Scene,
|
scene: &Scene,
|
||||||
input_chan: Arc<Mutex<Receiver<Request>>>,
|
input_chan: channel::Receiver<Request>,
|
||||||
output_chan: &SyncSender<Response>,
|
output_chan: &channel::Sender<Response>,
|
||||||
) {
|
) {
|
||||||
loop {
|
for req in input_chan {
|
||||||
match input_chan.lock().unwrap().recv() {
|
match req {
|
||||||
Err(err) => {
|
Request::Line { width, y } => {
|
||||||
info!("Shutting down render_worker {}: {}", tid, err);
|
let pixels = (0..width).map(|x| render_pixel(scene, x, y)).collect();
|
||||||
return;
|
output_chan.send(Response::Line { width, y, pixels });
|
||||||
|
}
|
||||||
|
Request::Pixel { x, y } => {
|
||||||
|
let pixel = render_pixel(scene, x, y);
|
||||||
|
output_chan.send(Response::Pixel { x, y, pixel });
|
||||||
}
|
}
|
||||||
Ok(req) => match req {
|
|
||||||
Request::Line { width, y } => {
|
|
||||||
let pixels = (0..width).map(|x| render_pixel(scene, x, y)).collect();
|
|
||||||
output_chan.send(Response::Line { width, y, pixels });
|
|
||||||
}
|
|
||||||
Request::Pixel { x, y } => {
|
|
||||||
let pixel = render_pixel(scene, x, y);
|
|
||||||
output_chan.send(Response::Pixel { x, y, pixel });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
trace!(target: "renderer", "Shutting down worker {}", tid);
|
trace!(target: "renderer", "Shutting down worker {}", tid);
|
||||||
@ -285,11 +275,10 @@ fn render_worker(
|
|||||||
|
|
||||||
pub fn render(scene: Scene, output_dir: &Path) -> std::result::Result<(), std::io::Error> {
|
pub fn render(scene: Scene, output_dir: &Path) -> std::result::Result<(), std::io::Error> {
|
||||||
let num_threads = scene.num_threads.unwrap_or_else(num_cpus::get);
|
let num_threads = scene.num_threads.unwrap_or_else(num_cpus::get);
|
||||||
let (pixel_req_tx, pixel_req_rx) = sync_channel(2 * num_threads);
|
let (pixel_req_tx, pixel_req_rx) = channel::bounded(2 * num_threads);
|
||||||
let (pixel_resp_tx, pixel_resp_rx) = sync_channel(2 * num_threads);
|
let (pixel_resp_tx, pixel_resp_rx) = channel::bounded(2 * num_threads);
|
||||||
|
|
||||||
let scene = Arc::new(scene);
|
let scene = sync::Arc::new(scene);
|
||||||
let pixel_req_rx = Arc::new(Mutex::new(pixel_req_rx));
|
|
||||||
println!("Creating {} render threads", num_threads);
|
println!("Creating {} render threads", num_threads);
|
||||||
for i in 0..num_threads {
|
for i in 0..num_threads {
|
||||||
let s = sync::Arc::clone(&scene);
|
let s = sync::Arc::clone(&scene);
|
||||||
@ -304,8 +293,8 @@ pub fn render(scene: Scene, output_dir: &Path) -> std::result::Result<(), std::i
|
|||||||
|
|
||||||
let (w, h) = (scene.width, scene.height);
|
let (w, h) = (scene.width, scene.height);
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let batch_line_requests = true;
|
let batch_by_line = true;
|
||||||
if batch_line_requests {
|
if batch_by_line {
|
||||||
for y in 0..h {
|
for y in 0..h {
|
||||||
pixel_req_tx.send(Request::Line { width: w, y });
|
pixel_req_tx.send(Request::Line { width: w, y });
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,7 +32,7 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
time_max,
|
time_max,
|
||||||
);
|
);
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
let mut grid: Vec<Box<dyn Hit>> = Vec::new();
|
let mut grid: Vec<Box<Hit>> = Vec::new();
|
||||||
let len = 1000;
|
let len = 1000;
|
||||||
for x in 0..len {
|
for x in 0..len {
|
||||||
for z in 0..len {
|
for z in 0..len {
|
||||||
@ -50,7 +50,7 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let world: Box<dyn Hit>;
|
let world: Box<Hit>;
|
||||||
if opt.use_accel {
|
if opt.use_accel {
|
||||||
let use_kd = true;
|
let use_kd = true;
|
||||||
if use_kd {
|
if use_kd {
|
||||||
|
|||||||
@ -40,7 +40,7 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
} else {
|
} else {
|
||||||
[0.4, 1.0, 0.4]
|
[0.4, 1.0, 0.4]
|
||||||
};
|
};
|
||||||
let world: Box<dyn Hit> = if opt.use_accel {
|
let world: Box<Hit> = if opt.use_accel {
|
||||||
Box::new(KDTree::new(random_scene(ground_color), time_min, time_max))
|
Box::new(KDTree::new(random_scene(ground_color), time_min, time_max))
|
||||||
} else {
|
} else {
|
||||||
Box::new(HitableList::new(random_scene(ground_color)))
|
Box::new(HitableList::new(random_scene(ground_color)))
|
||||||
@ -59,13 +59,13 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn random_scene<V>(ground_color: V) -> Vec<Box<dyn Hit>>
|
fn random_scene<V>(ground_color: V) -> Vec<Box<Hit>>
|
||||||
where
|
where
|
||||||
V: Into<Vec3>,
|
V: Into<Vec3>,
|
||||||
{
|
{
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
let checker = true;
|
let checker = true;
|
||||||
let ground_material: Box<dyn Material> = if checker {
|
let ground_material: Box<Material> = if checker {
|
||||||
Box::new(Lambertian::new(CheckerTexture::new(
|
Box::new(Lambertian::new(CheckerTexture::new(
|
||||||
ConstantTexture::new([0., 0., 0.]),
|
ConstantTexture::new([0., 0., 0.]),
|
||||||
ConstantTexture::new(ground_color),
|
ConstantTexture::new(ground_color),
|
||||||
@ -74,7 +74,7 @@ where
|
|||||||
Box::new(Lambertian::new(ConstantTexture::new(ground_color)))
|
Box::new(Lambertian::new(ConstantTexture::new(ground_color)))
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut objects: Vec<Box<dyn Hit>> = vec![Box::new(Sphere::new(
|
let mut objects: Vec<Box<Hit>> = vec![Box::new(Sphere::new(
|
||||||
[0., -1000., 0.],
|
[0., -1000., 0.],
|
||||||
1000.,
|
1000.,
|
||||||
ground_material,
|
ground_material,
|
||||||
@ -86,7 +86,7 @@ where
|
|||||||
let choose_mat = random();
|
let choose_mat = random();
|
||||||
let center = Vec3::new(a as f32 + 0.9 * random(), 0.2, b as f32 + 0.9 * random());
|
let center = Vec3::new(a as f32 + 0.9 * random(), 0.2, b as f32 + 0.9 * random());
|
||||||
if (center - Vec3::new(4., 0.2, 0.)).length() > 0.9 {
|
if (center - Vec3::new(4., 0.2, 0.)).length() > 0.9 {
|
||||||
let sphere: Box<dyn Hit> = if choose_mat < 0.8 {
|
let sphere: Box<Hit> = if choose_mat < 0.8 {
|
||||||
// diffuse
|
// diffuse
|
||||||
Box::new(Sphere::new(
|
Box::new(Sphere::new(
|
||||||
center,
|
center,
|
||||||
@ -120,7 +120,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let more: Vec<Box<dyn Hit>> = vec![
|
let more: Vec<Box<Hit>> = vec![
|
||||||
Box::new(Sphere::new(
|
Box::new(Sphere::new(
|
||||||
Vec3::new(0., 1., 0.),
|
Vec3::new(0., 1., 0.),
|
||||||
1.0,
|
1.0,
|
||||||
|
|||||||
@ -58,7 +58,7 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
time_max,
|
time_max,
|
||||||
);
|
);
|
||||||
trace!(target: "bvh", "World {}", b);
|
trace!(target: "bvh", "World {}", b);
|
||||||
let world: Box<dyn Hit> = Box::new(b);
|
let world: Box<Hit> = Box::new(b);
|
||||||
Scene {
|
Scene {
|
||||||
camera,
|
camera,
|
||||||
world,
|
world,
|
||||||
|
|||||||
@ -37,7 +37,7 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
time_max,
|
time_max,
|
||||||
);
|
);
|
||||||
|
|
||||||
let objects: Vec<Box<dyn Hit>> = vec![
|
let objects: Vec<Box<Hit>> = vec![
|
||||||
// Box1
|
// Box1
|
||||||
Box::new(Translate::new(
|
Box::new(Translate::new(
|
||||||
RotateY::new(
|
RotateY::new(
|
||||||
@ -121,7 +121,7 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
Lambertian::new(ConstantTexture::new(Vec3::new(0.73, 0.73, 0.73))),
|
Lambertian::new(ConstantTexture::new(Vec3::new(0.73, 0.73, 0.73))),
|
||||||
))),
|
))),
|
||||||
];
|
];
|
||||||
let world: Box<dyn Hit> = if opt.use_accel {
|
let world: Box<Hit> = if opt.use_accel {
|
||||||
Box::new(KDTree::new(objects, time_min, time_max))
|
Box::new(KDTree::new(objects, time_min, time_max))
|
||||||
} else {
|
} else {
|
||||||
Box::new(HitableList::new(objects))
|
Box::new(HitableList::new(objects))
|
||||||
|
|||||||
@ -40,12 +40,11 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let red = Lambertian::new(ConstantTexture::new([0.65, 0.05, 0.05]));
|
let red = Lambertian::new(ConstantTexture::new([0.65, 0.05, 0.05]));
|
||||||
let white: Arc<dyn Material> =
|
let white: Arc<Material> = Arc::new(Lambertian::new(ConstantTexture::new([0.73, 0.73, 0.73])));
|
||||||
Arc::new(Lambertian::new(ConstantTexture::new([0.73, 0.73, 0.73])));
|
|
||||||
let green = Lambertian::new(ConstantTexture::new([0.12, 0.45, 0.15]));
|
let green = Lambertian::new(ConstantTexture::new([0.12, 0.45, 0.15]));
|
||||||
let light = DiffuseLight::new(ConstantTexture::new([7., 7., 7.]));
|
let light = DiffuseLight::new(ConstantTexture::new([7., 7., 7.]));
|
||||||
|
|
||||||
let objects: Vec<Box<dyn Hit>> = vec![
|
let objects: Vec<Box<Hit>> = vec![
|
||||||
// White smoke box on the right
|
// White smoke box on the right
|
||||||
Box::new(ConstantMedium::new(
|
Box::new(ConstantMedium::new(
|
||||||
Translate::new(
|
Translate::new(
|
||||||
@ -107,7 +106,7 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
Arc::clone(&white),
|
Arc::clone(&white),
|
||||||
))),
|
))),
|
||||||
];
|
];
|
||||||
let world: Box<dyn Hit> = if opt.use_accel {
|
let world: Box<Hit> = if opt.use_accel {
|
||||||
Box::new(KDTree::new(objects, time_min, time_max))
|
Box::new(KDTree::new(objects, time_min, time_max))
|
||||||
} else {
|
} else {
|
||||||
Box::new(HitableList::new(objects))
|
Box::new(HitableList::new(objects))
|
||||||
|
|||||||
@ -51,12 +51,10 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
let nb = 20;
|
let nb = 20;
|
||||||
|
|
||||||
let rng = &mut rand::thread_rng();
|
let rng = &mut rand::thread_rng();
|
||||||
let mut boxlist: Vec<Box<dyn Hit>> = Vec::with_capacity(10000);
|
let mut boxlist: Vec<Box<Hit>> = Vec::with_capacity(10000);
|
||||||
let mut list: Vec<Box<dyn Hit>> = Vec::new();
|
let mut list: Vec<Box<Hit>> = Vec::new();
|
||||||
let white: Arc<dyn Material> =
|
let white: Arc<Material> = Arc::new(Lambertian::new(ConstantTexture::new([0.73, 0.73, 0.73])));
|
||||||
Arc::new(Lambertian::new(ConstantTexture::new([0.73, 0.73, 0.73])));
|
let ground: Arc<Material> = Arc::new(Lambertian::new(ConstantTexture::new([0.48, 0.83, 0.53])));
|
||||||
let ground: Arc<dyn Material> =
|
|
||||||
Arc::new(Lambertian::new(ConstantTexture::new([0.48, 0.83, 0.53])));
|
|
||||||
for i in 0..nb {
|
for i in 0..nb {
|
||||||
for j in 0..nb {
|
for j in 0..nb {
|
||||||
let w = 100.;
|
let w = 100.;
|
||||||
@ -104,8 +102,7 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
)));
|
)));
|
||||||
|
|
||||||
// Blue smokey glass ball lower-left
|
// Blue smokey glass ball lower-left
|
||||||
let boundary: Arc<dyn Hit> =
|
let boundary: Arc<Hit> = Arc::new(Sphere::new([360., 150., 145.], 70., Dielectric::new(1.5)));
|
||||||
Arc::new(Sphere::new([360., 150., 145.], 70., Dielectric::new(1.5)));
|
|
||||||
list.push(Box::new(Arc::clone(&boundary)));
|
list.push(Box::new(Arc::clone(&boundary)));
|
||||||
list.push(Box::new(ConstantMedium::new(
|
list.push(Box::new(ConstantMedium::new(
|
||||||
Arc::clone(&boundary),
|
Arc::clone(&boundary),
|
||||||
@ -114,7 +111,7 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
)));
|
)));
|
||||||
|
|
||||||
// General white mist over whole scene
|
// General white mist over whole scene
|
||||||
let boundary: Arc<dyn Hit> = Arc::new(Sphere::new([0., 0., 0.], 5000., Dielectric::new(1.5)));
|
let boundary: Arc<Hit> = Arc::new(Sphere::new([0., 0., 0.], 5000., Dielectric::new(1.5)));
|
||||||
list.push(Box::new(Arc::clone(&boundary)));
|
list.push(Box::new(Arc::clone(&boundary)));
|
||||||
list.push(Box::new(ConstantMedium::new(
|
list.push(Box::new(ConstantMedium::new(
|
||||||
Arc::clone(&boundary),
|
Arc::clone(&boundary),
|
||||||
@ -148,7 +145,7 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
|
|
||||||
// White 'cube' made of 1000 spheres
|
// White 'cube' made of 1000 spheres
|
||||||
let ns = 1000;
|
let ns = 1000;
|
||||||
let mut boxlist: Vec<Box<dyn Hit>> = Vec::with_capacity(1000);
|
let mut boxlist: Vec<Box<Hit>> = Vec::with_capacity(1000);
|
||||||
for _ in 0..ns {
|
for _ in 0..ns {
|
||||||
boxlist.push(Box::new(Sphere::new(
|
boxlist.push(Box::new(Sphere::new(
|
||||||
[
|
[
|
||||||
|
|||||||
@ -15,7 +15,6 @@ use crate::renderer::Opt;
|
|||||||
use crate::renderer::Scene;
|
use crate::renderer::Scene;
|
||||||
use crate::sphere::Sphere;
|
use crate::sphere::Sphere;
|
||||||
use crate::texture::ConstantTexture;
|
use crate::texture::ConstantTexture;
|
||||||
use crate::texture::ImageTexture;
|
|
||||||
use crate::texture::Mandelbrot;
|
use crate::texture::Mandelbrot;
|
||||||
use crate::texture::NoiseTexture;
|
use crate::texture::NoiseTexture;
|
||||||
use crate::vec3::Vec3;
|
use crate::vec3::Vec3;
|
||||||
@ -45,32 +44,28 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
Box::new(ConstantTexture::new(Vec3::new(0.4, 1.0, 0.4)))
|
Box::new(ConstantTexture::new(Vec3::new(0.4, 1.0, 0.4)))
|
||||||
};
|
};
|
||||||
|
|
||||||
let world_image_bytes = include_bytes!("../../images/world.jpg");
|
|
||||||
let it = ImageTexture::new(image::load_from_memory(world_image_bytes).unwrap().to_rgb());
|
|
||||||
let noise_source = Perlin::new(rng);
|
let noise_source = Perlin::new(rng);
|
||||||
let noise_type = NoiseType::Scale(10.);
|
let noise_type = NoiseType::Scale(10.);
|
||||||
let objects: Vec<Box<dyn Hit>> = vec![
|
let objects: Vec<Box<Hit>> = vec![
|
||||||
// Textured globe
|
// Textured globe
|
||||||
// Box::new(Sphere::new(Vec3::new(0., 2., 0.), 2.0, Lambertian::new(it))),
|
// Box::new(Sphere::new(Vec3::new(0., 2., 0.), 2.0, Lambertian::new(it))),
|
||||||
Box::new(Sphere::new(
|
Box::new(Sphere::new(
|
||||||
Vec3::new(0., 2., 0.),
|
Vec3::new(0., 2., 0.),
|
||||||
2.0,
|
2.0,
|
||||||
DiffuseLight::new(it),
|
DiffuseLight::new(Mandelbrot::default()),
|
||||||
|
)),
|
||||||
|
// Earth sized sphere
|
||||||
|
Box::new(Sphere::new(
|
||||||
|
Vec3::new(0., -1000., 0.),
|
||||||
|
1000.,
|
||||||
|
// Box::new(Lambertian::new(ground_color)),
|
||||||
|
Lambertian::new(NoiseTexture::new(noise_source, noise_type)),
|
||||||
)),
|
)),
|
||||||
// Ground
|
|
||||||
Box::new(XZRect::new(
|
Box::new(XZRect::new(
|
||||||
-100.,
|
-100.,
|
||||||
100.,
|
100.,
|
||||||
-100.,
|
-100.,
|
||||||
1000.,
|
1000.,
|
||||||
-60.,
|
|
||||||
DiffuseLight::new(Mandelbrot::default()),
|
|
||||||
)),
|
|
||||||
Box::new(XZRect::new(
|
|
||||||
-100.,
|
|
||||||
100.,
|
|
||||||
-100.,
|
|
||||||
200.,
|
|
||||||
60.,
|
60.,
|
||||||
DiffuseLight::new(ConstantTexture::new(Vec3::new(1., 1., 1.))),
|
DiffuseLight::new(ConstantTexture::new(Vec3::new(1., 1., 1.))),
|
||||||
)),
|
)),
|
||||||
@ -112,7 +107,7 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
1.,
|
1.,
|
||||||
3.,
|
3.,
|
||||||
4.,
|
4.,
|
||||||
Lambertian::new(NoiseTexture::new(noise_source, noise_type)),
|
DiffuseLight::new(Mandelbrot::default()),
|
||||||
)),
|
)),
|
||||||
/*
|
/*
|
||||||
Box::new(Sphere::new(
|
Box::new(Sphere::new(
|
||||||
@ -140,7 +135,7 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
)),
|
)),
|
||||||
*/
|
*/
|
||||||
];
|
];
|
||||||
let world: Box<dyn Hit> = if opt.use_accel {
|
let world: Box<Hit> = if opt.use_accel {
|
||||||
Box::new(KDTree::new(objects, time_min, time_max))
|
Box::new(KDTree::new(objects, time_min, time_max))
|
||||||
} else {
|
} else {
|
||||||
Box::new(HitableList::new(objects))
|
Box::new(HitableList::new(objects))
|
||||||
|
|||||||
@ -42,9 +42,9 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
size: 32,
|
size: 32,
|
||||||
scale: 0.05,
|
scale: 0.05,
|
||||||
};
|
};
|
||||||
let pertext: Arc<dyn Texture> = Arc::new(NoiseTexture::new(noise_source, noise_type));
|
let pertext: Arc<Texture> = Arc::new(NoiseTexture::new(noise_source, noise_type));
|
||||||
|
|
||||||
let objects: Vec<Box<dyn Hit>> = vec![
|
let objects: Vec<Box<Hit>> = vec![
|
||||||
Box::new(Sphere::new(
|
Box::new(Sphere::new(
|
||||||
Vec3::new(0., -1000., 0.),
|
Vec3::new(0., -1000., 0.),
|
||||||
1000.,
|
1000.,
|
||||||
@ -56,7 +56,7 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
Lambertian::new(Arc::clone(&pertext)),
|
Lambertian::new(Arc::clone(&pertext)),
|
||||||
)),
|
)),
|
||||||
];
|
];
|
||||||
let world: Box<dyn Hit> = if opt.use_accel {
|
let world: Box<Hit> = if opt.use_accel {
|
||||||
Box::new(KDTree::new(objects, time_min, time_max))
|
Box::new(KDTree::new(objects, time_min, time_max))
|
||||||
} else {
|
} else {
|
||||||
Box::new(HitableList::new(objects))
|
Box::new(HitableList::new(objects))
|
||||||
|
|||||||
@ -49,7 +49,7 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
let it = ImageTexture::new(image::load_from_memory(world_image_bytes).unwrap().to_rgb());
|
let it = ImageTexture::new(image::load_from_memory(world_image_bytes).unwrap().to_rgb());
|
||||||
let noise_source = Perlin::new(rng);
|
let noise_source = Perlin::new(rng);
|
||||||
let noise_type = NoiseType::Scale(10.);
|
let noise_type = NoiseType::Scale(10.);
|
||||||
let objects: Vec<Box<dyn Hit>> = vec![
|
let objects: Vec<Box<Hit>> = vec![
|
||||||
// Big sphere
|
// Big sphere
|
||||||
Box::new(Sphere::new(Vec3::new(0., 2., 0.), 2.0, Lambertian::new(it))),
|
Box::new(Sphere::new(Vec3::new(0., 2., 0.), 2.0, Lambertian::new(it))),
|
||||||
// Earth sized sphere
|
// Earth sized sphere
|
||||||
@ -133,7 +133,7 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
)),
|
)),
|
||||||
*/
|
*/
|
||||||
];
|
];
|
||||||
let world: Box<dyn Hit> = if opt.use_accel {
|
let world: Box<Hit> = if opt.use_accel {
|
||||||
Box::new(KDTree::new(objects, time_min, time_max))
|
Box::new(KDTree::new(objects, time_min, time_max))
|
||||||
} else {
|
} else {
|
||||||
Box::new(HitableList::new(objects))
|
Box::new(HitableList::new(objects))
|
||||||
|
|||||||
@ -35,7 +35,7 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
ConstantTexture::new(Vec3::new(0.4, 1.0, 0.4))
|
ConstantTexture::new(Vec3::new(0.4, 1.0, 0.4))
|
||||||
};
|
};
|
||||||
|
|
||||||
let objects: Vec<Box<dyn Hit>> = vec![
|
let objects: Vec<Box<Hit>> = vec![
|
||||||
//let world: Box<Hit> = Box::new(HitableList::new(vec![
|
//let world: Box<Hit> = Box::new(HitableList::new(vec![
|
||||||
Box::new(Sphere::new(
|
Box::new(Sphere::new(
|
||||||
Vec3::new(0., 0., -1.),
|
Vec3::new(0., 0., -1.),
|
||||||
@ -61,7 +61,7 @@ pub fn new(opt: &Opt) -> Scene {
|
|||||||
Lambertian::new(ConstantTexture::new(Vec3::new(0.2, 0.8, 0.2))),
|
Lambertian::new(ConstantTexture::new(Vec3::new(0.2, 0.8, 0.2))),
|
||||||
)),
|
)),
|
||||||
];
|
];
|
||||||
let world: Box<dyn Hit> = if opt.use_accel {
|
let world: Box<Hit> = if opt.use_accel {
|
||||||
Box::new(KDTree::new(objects, time_min, time_max))
|
Box::new(KDTree::new(objects, time_min, time_max))
|
||||||
} else {
|
} else {
|
||||||
Box::new(HitableList::new(objects))
|
Box::new(HitableList::new(objects))
|
||||||
|
|||||||
@ -19,7 +19,7 @@ pub trait Texture: Send + Sync {
|
|||||||
fn value(&self, u: f32, v: f32, p: Vec3) -> Vec3;
|
fn value(&self, u: f32, v: f32, p: Vec3) -> Vec3;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Texture for Arc<dyn Texture> {
|
impl Texture for Arc<Texture> {
|
||||||
fn value(&self, u: f32, v: f32, p: Vec3) -> Vec3 {
|
fn value(&self, u: f32, v: f32, p: Vec3) -> Vec3 {
|
||||||
(**self).value(u, v, p)
|
(**self).value(u, v, p)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user