wip: parallelization
This commit is contained in:
142
src/camera.rs
142
src/camera.rs
@@ -1,34 +1,23 @@
|
||||
use std::{f32::consts::PI, sync::Arc};
|
||||
use std::f32::consts::PI;
|
||||
|
||||
use log::info;
|
||||
|
||||
use crate::{
|
||||
objects::{hit::Hit, traits::Hittable},
|
||||
ray::Ray,
|
||||
vec3::{Colour, Vec3},
|
||||
};
|
||||
use crate::{ray::Ray, vec3::Vec3};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Camera {
|
||||
// output
|
||||
image_width: u32,
|
||||
image_height: u32,
|
||||
|
||||
// raytracing
|
||||
anti_alias_rate: u32,
|
||||
max_depth: u32,
|
||||
pixel00_loc: Vec3,
|
||||
pixel_delta_u: Vec3,
|
||||
pixel_delta_v: Vec3,
|
||||
pub anti_alias_rate: u32,
|
||||
pub pixel00_loc: Vec3,
|
||||
pub pixel_delta_u: Vec3,
|
||||
pub pixel_delta_v: Vec3,
|
||||
|
||||
// camera
|
||||
dirty: bool,
|
||||
fov: f32,
|
||||
look_from: Vec3,
|
||||
look_at: Vec3,
|
||||
pub fov: f32,
|
||||
pub look_from: Vec3,
|
||||
pub look_at: Vec3,
|
||||
vup: Vec3,
|
||||
defocus_angle: f32,
|
||||
focus_dist: f32,
|
||||
pub defocus_angle: f32,
|
||||
pub focus_dist: f32,
|
||||
|
||||
// camera helpers
|
||||
u: Vec3,
|
||||
@@ -44,12 +33,9 @@ fn deg_to_rad(deg: f32) -> f32 {
|
||||
}
|
||||
|
||||
impl Camera {
|
||||
pub fn new(image_width: u32, image_height: u32) -> Self {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
image_width,
|
||||
image_height,
|
||||
anti_alias_rate: 1,
|
||||
max_depth: 10,
|
||||
dirty: true,
|
||||
fov: 60.,
|
||||
pixel00_loc: Vec3::default(),
|
||||
@@ -69,10 +55,7 @@ impl Camera {
|
||||
}
|
||||
|
||||
pub fn new_full(
|
||||
image_width: u32,
|
||||
image_height: u32,
|
||||
anti_alias_rate: u32,
|
||||
max_depth: u32,
|
||||
fov: f32,
|
||||
look_from: Vec3,
|
||||
look_at: Vec3,
|
||||
@@ -81,10 +64,7 @@ impl Camera {
|
||||
focus_dist: f32,
|
||||
) -> Self {
|
||||
Self {
|
||||
image_width,
|
||||
image_height,
|
||||
anti_alias_rate,
|
||||
max_depth,
|
||||
pixel00_loc: Vec3::default(),
|
||||
pixel_delta_u: Vec3::default(),
|
||||
pixel_delta_v: Vec3::default(),
|
||||
@@ -103,7 +83,11 @@ impl Camera {
|
||||
}
|
||||
}
|
||||
|
||||
fn init(&mut self) {
|
||||
pub fn init(&mut self, w: f32, hi: f32) {
|
||||
if !self.dirty {
|
||||
return;
|
||||
}
|
||||
|
||||
// camera
|
||||
let theta = deg_to_rad(self.fov);
|
||||
let h = (theta / 2.).tan();
|
||||
@@ -113,13 +97,13 @@ impl Camera {
|
||||
|
||||
// viewport
|
||||
let viewport_height = 2. * h * self.focus_dist;
|
||||
let viewport_width = viewport_height * (self.image_width as f32 / self.image_height as f32);
|
||||
let viewport_width = viewport_height * (w / hi);
|
||||
let viewport_u = viewport_width * self.u;
|
||||
let viewport_v = viewport_height * -self.v;
|
||||
|
||||
// variables
|
||||
self.pixel_delta_u = viewport_u / self.image_width as f32;
|
||||
self.pixel_delta_v = viewport_v / self.image_height as f32;
|
||||
self.pixel_delta_u = viewport_u / w;
|
||||
self.pixel_delta_v = viewport_v / hi;
|
||||
self.pixel00_loc =
|
||||
self.look_from - (self.focus_dist * self.w) - viewport_u / 2. - viewport_v / 2.;
|
||||
self.dirty = false;
|
||||
@@ -131,6 +115,19 @@ impl Camera {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_ray(&self, pixel_tl: Vec3, x: u32, y: u32) -> Ray {
|
||||
let pixel_loc = pixel_tl
|
||||
+ (x * self.pixel_delta_u / (self.anti_alias_rate + 1) as f32)
|
||||
+ (y * self.pixel_delta_v / (self.anti_alias_rate + 1) as f32);
|
||||
let ray_orig = if self.defocus_angle > 0. {
|
||||
self.defocus_disk_sample()
|
||||
} else {
|
||||
self.look_from
|
||||
};
|
||||
let ray_dir = pixel_loc - ray_orig;
|
||||
Ray::new(ray_orig, ray_dir)
|
||||
}
|
||||
|
||||
pub fn set_fov(&mut self, fov: f32) {
|
||||
if self.fov != fov {
|
||||
self.fov = fov;
|
||||
@@ -138,13 +135,6 @@ impl Camera {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_max_depth(&mut self, depth: u32) {
|
||||
if self.max_depth != depth {
|
||||
self.max_depth = depth;
|
||||
self.dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_anti_alias_rate(&mut self, rate: u32) {
|
||||
if self.anti_alias_rate != rate {
|
||||
self.anti_alias_rate = rate;
|
||||
@@ -181,72 +171,8 @@ impl Camera {
|
||||
}
|
||||
}
|
||||
|
||||
fn defocus_disk_sample(&self) -> Vec3 {
|
||||
pub fn defocus_disk_sample(&self) -> Vec3 {
|
||||
let p = Vec3::random_in_unit_disk();
|
||||
self.look_from + (p.x() * self.defocus_disk_u) + (p.y() * self.defocus_disk_v)
|
||||
}
|
||||
|
||||
pub fn render(&mut self, hittables: &Vec<Arc<dyn Hittable>>) {
|
||||
if self.dirty {
|
||||
self.init()
|
||||
}
|
||||
|
||||
let mut imgbuf = image::ImageBuffer::new(self.image_width, self.image_height);
|
||||
|
||||
// render
|
||||
for j in 0..self.image_height {
|
||||
info!("{}\tScanlines remaining.", (self.image_height - j));
|
||||
for i in 0..self.image_width {
|
||||
let pixel_tl =
|
||||
self.pixel00_loc + (i * self.pixel_delta_u) + (j * self.pixel_delta_v);
|
||||
|
||||
let mut pixel_colour = Colour::default();
|
||||
for y in 1..(self.anti_alias_rate + 1) {
|
||||
for x in 1..(self.anti_alias_rate + 1) {
|
||||
let pixel_loc = pixel_tl
|
||||
+ (x * self.pixel_delta_u / (self.anti_alias_rate + 1) as f32)
|
||||
+ (y * self.pixel_delta_v / (self.anti_alias_rate + 1) as f32);
|
||||
let ray_orig = if self.defocus_angle > 0. {
|
||||
self.defocus_disk_sample()
|
||||
} else {
|
||||
self.look_from
|
||||
};
|
||||
let ray_dir = pixel_loc - ray_orig;
|
||||
let r = Ray::new(ray_orig, ray_dir);
|
||||
pixel_colour += self.ray_colour(hittables, &r, self.max_depth);
|
||||
}
|
||||
}
|
||||
|
||||
let pixel = imgbuf.get_pixel_mut(i, j);
|
||||
*pixel =
|
||||
(pixel_colour / (self.anti_alias_rate * self.anti_alias_rate) as f32).output();
|
||||
}
|
||||
}
|
||||
|
||||
info!("Writing image file...");
|
||||
imgbuf.save("output.png").unwrap();
|
||||
}
|
||||
|
||||
fn ray_colour(&self, hittables: &Vec<Arc<dyn Hittable>>, r: &Ray, depth: u32) -> Colour {
|
||||
if depth == 0 {
|
||||
return Colour::default();
|
||||
}
|
||||
|
||||
let closest = Hit::hit_list(hittables, r);
|
||||
if let Some(hit) = closest {
|
||||
if let Some((scattered, att)) = hit.mat().scatter(&hit, r) {
|
||||
if let Some(ray) = scattered {
|
||||
return att * self.ray_colour(hittables, &ray, depth - 1);
|
||||
}
|
||||
return att;
|
||||
}
|
||||
return Colour::default();
|
||||
}
|
||||
|
||||
// background
|
||||
let unit_dir = r.dir().get_unit();
|
||||
let a = 0.5 * (unit_dir.y() + 1.);
|
||||
|
||||
(1.0 - a) * Colour::new(1., 1., 1.) + a * Colour::new(0.5, 0.7, 1.0)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user