pbrt/src/cameras/realistic.rs

90 lines
3 KiB
Rust

use ash::vk::Image;
use shared::cameras::{Mapping, RealisticCamera, realistic::LensElementInterface};
struct RealisticCameraData {
aperture_image: Arc<Image>,
element_interfaces: Vec<LensElementInterface>,
}
pub struct RealisticCameraHost {
device: RealisticCamera,
data: RealisticCameraData,
}
impl RealisticCameraHost {
pub fn new(
base: CameraBase,
lens_params: &[Float],
focus_distance: Float,
set_aperture_diameter: Float,
aperture_image: Arc<Image>,
) -> Self {
let film_ptr = base.film;
if film_ptr.is_null() {
panic!("Camera must have a film");
}
let film = &*film_ptr;
let aspect = film.full_resolution().x() as Float / film.full_resolution().y() as Float;
let diagonal = film.diagonal();
let x = (square(diagonal) / (1.0 + square(diagonal))).sqrt();
let y = x * aspect;
let physical_extent =
Bounds2f::from_points(Point2f::new(-x / 2., -y / 2.), Point2f::new(x / 2., y / 2.));
let mut element_interface: Vec<LensElementInterface> = Vec::new();
for i in (0..lens_params.len()).step_by(4) {
let curvature_radius = lens_params[i] / 1000.0;
let thickness = lens_params[i + 1] / 1000.0;
let eta = lens_params[i + 2];
let mut aperture_diameter = lens_params[i + 3] / 1000.0;
if curvature_radius == 0.0 {
aperture_diameter /= 1000.0;
if set_aperture_diameter > aperture_diameter {
println!("Aperture is larger than possible")
} else {
aperture_diameter = set_aperture_diameter;
}
}
let el_int = LensElementInterface {
curvature_radius,
thickness,
eta,
aperture_radius: aperture_diameter / 2.0,
};
element_interface.push(el_int);
}
let half_diag = film.diagonal() / 2.0;
let mut exit_pupil_bounds = [Bounds2f::default(); EXIT_PUPIL_SAMPLES];
for i in 0..EXIT_PUPIL_SAMPLES {
let r0 = (i as Float / EXIT_PUPIL_SAMPLES as Float) * half_diag;
let r1 = ((i + 1) as Float / EXIT_PUPIL_SAMPLES as Float) * half_diag;
exit_pupil_bounds[i] = Self::compute_exit_pupil_bounds(&element_interface, r0, r1);
}
let n_elements = element_interface.len();
let element_interfaces = element_interface.as_ptr();
std::mem::forget(element_interface);
let data = RealisticCameraData {
element_interfaces,
aperture_image,
};
let device = RealisticCamera {
base,
focus_distance,
element_interfaces: Ptr::from(element_interfaces),
n_elements,
physical_extent,
set_aperture_diameter,
aperture_image,
exit_pupil_bounds,
};
Self { device, data }
}
}