Skip to content

Commit

Permalink
rayon and 11.4 - schlick approximation
Browse files Browse the repository at this point in the history
  • Loading branch information
grishy committed Feb 19, 2024
1 parent d8f63fe commit a4c6ead
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 29 deletions.
23 changes: 14 additions & 9 deletions src/camera.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use indicatif::ProgressIterator;
use indicatif::{ProgressBar, ProgressStyle};
use itertools::Itertools;
use rand::{self, Rng};
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use std::fs::File;
use std::ops::Range;

use std::io::prelude::*;
use std::ops::Range;

use crate::hittable::Hittable;
use crate::ray;
Expand Down Expand Up @@ -58,8 +57,8 @@ impl Camera {
pixel00_loc,
pixel_delta_u,
pixel_delta_v,
samples_per_pixel: 200,
max_depth: 30,
samples_per_pixel: 500,
max_depth: 20,
}
}

Expand All @@ -75,8 +74,10 @@ impl Camera {
.progress_chars("#>-"),
);

let pixels: Vec<String> = (0..self.image_height)
let pixels = (0..self.image_height)
.cartesian_product(0..self.image_width)
.collect::<Vec<(i32, i32)>>()
.into_par_iter()
.map(|(y, x)| {
// Send few rays to the pixel
let mut pixel_color = Color::new(0.0, 0.0, 0.0);
Expand All @@ -96,15 +97,17 @@ impl Camera {
);

pixel_color *= 256.0;

pb.inc(1);
format!(
"{} {} {}",
(pixel_color.x.clamp(0., 256.)) as i32,
(pixel_color.y.clamp(0., 256.)) as i32,
(pixel_color.z.clamp(0., 256.)) as i32
)
})
.progress_with(pb)
.collect();
.collect::<Vec<String>>()
.join("\n");

write!(
image_file,
Expand All @@ -116,9 +119,11 @@ impl Camera {
self.image_width,
self.image_height,
"255", // Max color value
pixels.join("\n")
pixels
)
.unwrap();

pb.finish()
}

// Get a randomly sampled camera ray for the pixel at location i,j.
Expand Down
4 changes: 2 additions & 2 deletions src/hittable.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::ops::Range;
use std::rc::Rc;
use std::sync::Arc;

use crate::material;
use crate::ray;
Expand All @@ -12,7 +12,7 @@ pub trait Hittable {
pub struct HitRecord {
pub p: Point3,
pub normal: Vector3,
pub material: Rc<dyn material::Material>,
pub material: Arc<dyn material::Material + Send + Sync>,
pub t: f64,
pub front_face: bool,
}
Expand Down
27 changes: 14 additions & 13 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@ mod sphere;
mod types;

use std::ops::Range;
use std::rc::Rc;
use std::sync::Arc;
use types::*;

pub struct HittableList {
objects: Vec<Box<dyn hittable::Hittable>>,
objects: Vec<Arc<dyn hittable::Hittable + Send + Sync>>,
}

impl HittableList {
fn new() -> HittableList {
HittableList { objects: vec![] }
}
fn add(&mut self, object: Box<dyn hittable::Hittable>) {
fn add(&mut self, object: Arc<dyn hittable::Hittable + Send + Sync>) {
self.objects.push(object);
}
}
Expand All @@ -34,35 +34,36 @@ impl hittable::Hittable for HittableList {
fn main() {
// Params
let aspect_ratio = 16.0 / 9.0;
let image_width = 1200;
let image_width = 1600;

// Camera
let camera = camera::Camera::new(aspect_ratio, image_width);

// World
let mut world = Box::new(HittableList::new());
let mut world = HittableList::new();

// Materials
let material_center = Rc::new(material::Lambertian::new(Color::new(0.1, 0.2, 0.5)));
let material_left = Rc::new(material::Dielectric::new(1.5));
let material_right = Rc::new(material::Metal::new(Color::new(0.8, 0.6, 0.2), 0.0));
let material_ground = Rc::new(material::Lambertian::new(Color::new(0.8, 0.8, 0.0)));
let material_center = Arc::new(material::Lambertian::new(Color::new(0.1, 0.2, 0.5)));
let material_left = Arc::new(material::Dielectric::new(1.5));
let material_right = Arc::new(material::Metal::new(Color::new(0.8, 0.6, 0.2), 0.5));
let material_ground = Arc::new(material::Lambertian::new(Color::new(0.8, 0.8, 0.0)));

world.add(Box::new(sphere::Sphere::new(
world.add(Arc::new(sphere::Sphere::new(
Point3::new(0.0, 0.0, -1.0),
0.5,
material_center,
)));
world.add(Box::new(sphere::Sphere::new(
world.add(Arc::new(sphere::Sphere::new(
Point3::new(-1.0, 0.0, -1.0),
0.5,
material_left,
)));
world.add(Box::new(sphere::Sphere::new(
world.add(Arc::new(sphere::Sphere::new(
Point3::new(1.0, 0.0, -1.0),
0.5,
material_right,
)));
world.add(Box::new(sphere::Sphere::new(
world.add(Arc::new(sphere::Sphere::new(
Point3::new(0.0, -100.5, -1.0),
100.0,
material_ground,
Expand Down
9 changes: 8 additions & 1 deletion src/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ fn refract(uv: &Vector3, n: &Vector3, etai_over_etat: f64) -> Vector3 {
r_out_perp + r_out_parallel
}

fn reflectance(cosine: f64, ref_idx: f64) -> f64 {
// Use Schlick's approximation for reflectance
let r0 = ((1.0 - ref_idx) / (1.0 + ref_idx)).powi(2);
r0 + (1.0 - r0) * (1.0 - cosine).powi(5)
}

pub trait Material {
fn scatter(
&self,
Expand Down Expand Up @@ -135,7 +141,8 @@ impl Material for Dielectric {
let sin_theta = (1.0 - cos_theta * cos_theta).sqrt();

let cannot_refract = refraction_ratio * sin_theta > 1.0;
let direction = if cannot_refract {
let is_reflectance = reflectance(cos_theta, refraction_ratio) > rand::thread_rng().gen();
let direction = if cannot_refract || is_reflectance {
reflect(&unit_direction, &hit_record.normal)
} else {
refract(&unit_direction, &hit_record.normal, refraction_ratio)
Expand Down
12 changes: 8 additions & 4 deletions src/sphere.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::ops::Range;
use std::rc::Rc;
use std::sync::Arc;

use crate::hittable;
use crate::hittable::length_squared;
Expand All @@ -11,10 +11,14 @@ use crate::types::*;
pub struct Sphere {
center: Point3,
radius: f64,
material: Rc<dyn material::Material>,
material: Arc<dyn material::Material + Send + Sync>,
}
impl Sphere {
pub fn new(center: Point3, radius: f64, material: Rc<dyn material::Material>) -> Sphere {
pub fn new(
center: Point3,
radius: f64,
material: Arc<dyn material::Material + Send + Sync>,
) -> Sphere {
Sphere {
center,
radius,
Expand Down Expand Up @@ -51,7 +55,7 @@ impl hittable::Hittable for Sphere {
t: root,
p: ray.at(root),
front_face: false,
material: self.material.clone(),
material: Arc::clone(&self.material),
normal: Vector3::zeros(),
};
let outward_normal = (ray.at(root) - self.center) / self.radius;
Expand Down

0 comments on commit a4c6ead

Please sign in to comment.