ft: 13: optional defocus blur
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
use std::{f32::consts::PI, sync::Arc};
|
||||
|
||||
use log::info;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::{
|
||||
objects::{hit::Hit, traits::Hittable},
|
||||
@@ -28,11 +27,15 @@ pub struct Camera {
|
||||
look_from: Vec3,
|
||||
look_at: Vec3,
|
||||
vup: Vec3,
|
||||
defocus_angle: f32,
|
||||
focus_dist: f32,
|
||||
|
||||
// camera helpers
|
||||
u: Vec3,
|
||||
v: Vec3,
|
||||
w: Vec3,
|
||||
defocus_disk_u: Vec3,
|
||||
defocus_disk_v: Vec3,
|
||||
}
|
||||
|
||||
// FIXME: kinda out of place in this file.
|
||||
@@ -55,9 +58,13 @@ impl Camera {
|
||||
look_from: Vec3::nil(),
|
||||
look_at: Vec3::new(0., 0., -1.),
|
||||
vup: Vec3::new(0., 1., 0.),
|
||||
defocus_angle: 0.,
|
||||
focus_dist: 10.,
|
||||
u: Vec3::default(),
|
||||
v: Vec3::default(),
|
||||
w: Vec3::default(),
|
||||
defocus_disk_u: Vec3::default(),
|
||||
defocus_disk_v: Vec3::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +77,8 @@ impl Camera {
|
||||
look_from: Vec3,
|
||||
look_at: Vec3,
|
||||
vup: Vec3,
|
||||
defocus_angle: f32,
|
||||
focus_dist: f32,
|
||||
) -> Self {
|
||||
Self {
|
||||
image_width,
|
||||
@@ -84,15 +93,18 @@ impl Camera {
|
||||
look_from,
|
||||
look_at,
|
||||
vup,
|
||||
defocus_angle,
|
||||
focus_dist,
|
||||
u: Vec3::default(),
|
||||
v: Vec3::default(),
|
||||
w: Vec3::default(),
|
||||
defocus_disk_u: Vec3::default(),
|
||||
defocus_disk_v: Vec3::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn init(&mut self) {
|
||||
// camera
|
||||
let focal_length = (self.look_from - self.look_at).length();
|
||||
let theta = deg_to_rad(self.fov);
|
||||
let h = (theta / 2.).tan();
|
||||
self.w = (self.look_from - self.look_at).get_unit();
|
||||
@@ -100,7 +112,7 @@ impl Camera {
|
||||
self.v = self.w.cross(&self.u);
|
||||
|
||||
// viewport
|
||||
let viewport_height = 2. * h * focal_length;
|
||||
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_u = viewport_width * self.u;
|
||||
let viewport_v = viewport_height * -self.v;
|
||||
@@ -109,8 +121,14 @@ impl Camera {
|
||||
self.pixel_delta_u = viewport_u / self.image_width as f32;
|
||||
self.pixel_delta_v = viewport_v / self.image_height as f32;
|
||||
self.pixel00_loc =
|
||||
self.look_from - (focal_length * self.w) - viewport_u / 2. - viewport_v / 2.;
|
||||
self.look_from - (self.focus_dist * self.w) - viewport_u / 2. - viewport_v / 2.;
|
||||
self.dirty = false;
|
||||
|
||||
if self.defocus_angle != 0. {
|
||||
let defocus_radius = self.focus_dist * deg_to_rad(self.defocus_angle/2.).tan();
|
||||
self.defocus_disk_u = self.u * defocus_radius;
|
||||
self.defocus_disk_v = self.v * defocus_radius;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_fov(&mut self, fov: f32) {
|
||||
@@ -155,6 +173,19 @@ impl Camera {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_defocus_blur(&mut self, defocus_angle: f32, focus_dist: f32) {
|
||||
if self.defocus_angle != defocus_angle || self.focus_dist != focus_dist {
|
||||
self.defocus_angle = defocus_angle;
|
||||
self.focus_dist = focus_dist;
|
||||
self.dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
fn defocus_disk_sample(&self) -> Vec3 {
|
||||
let p = Vec3::random_in_unit_disk();
|
||||
return 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()
|
||||
@@ -175,8 +206,9 @@ impl Camera {
|
||||
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_dir = pixel_loc - self.look_from;
|
||||
let r = Ray::new(self.look_from, ray_dir);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user