pbrt/src/films/gbuffer.rs

99 lines
3.3 KiB
Rust

use super::*;
use crate::core::film::{CreateFilmBase, PixelSensor};
use crate::utils::containers::Array2D;
use anyhow::{Result, anyhow};
use shared::core::film::{FilmBase, GBufferFilm};
use shared::core::filter::FilterTrait;
use shared::spectra::RGBColorSpace;
use shared::utils::AnimatedTransform;
use std::path::Path;
pub struct GBufferFilmHost {
pub device: GBufferFilm,
}
impl GBufferFilmHost {
pub fn new(
base: &FilmBase,
output_from_render: &AnimatedTransform,
apply_inverse: bool,
colorspace: &RGBColorSpace,
max_component_value: Float,
write_fp16: bool,
) -> Self {
assert!(!base.pixel_bounds.is_empty());
let sensor_ptr = base.sensor;
if sensor_ptr.is_null() {
panic!("Film must have a sensor");
}
let sensor = &*sensor_ptr;
let output_rgbf_from_sensor_rgb = colorspace.rgb_from_xyz * sensor.xyz_from_sensor_rgb;
let filter_integral = base.filter.integral();
let pixels = Array2D::new(base.pixel_bounds);
let device = GBufferFilm {
base: base.clone(),
output_from_render: *output_from_render,
apply_inverse,
pixels,
colorspace: colorspace.clone(),
max_component_value,
write_fp16,
filter_integral,
output_rgbf_from_sensor_rgb,
};
Self { device }
}
}
impl CreateFilm for GBufferFilm {
fn create(
params: &ParameterDictionary,
exposure_time: Float,
filter: Filter,
camera_transform: Option<CameraTransform>,
loc: &FileLoc,
_arena: &Arena,
) -> Result<Film> {
let colorspace = params.color_space.as_ref().unwrap();
let max_component_value = params.get_one_float("maxcomponentvalue", Float::INFINITY)?;
let write_fp16 = params.get_one_bool("savefp16", true)?;
let sensor = PixelSensor::create(params, colorspace.clone(), exposure_time, loc)?;
let film_base = FilmBase::create(params, filter, Some(&sensor.device()), loc)?;
let filename = params.get_one_string("filename", "pbrt.exr")?;
if Path::new(&filename).extension() != Some("exr".as_ref()) {
return Err(anyhow!("{}: EXR is the only format supported by GBufferFilm", loc).into());
}
let coords_system = params.get_one_string("coordinatesystem", "camera")?;
let mut apply_inverse = false;
let camera_transform =
camera_transform.ok_or_else(|| anyhow!("GBufferFilm requires a camera_transform"))?;
let output_from_render = if coords_system == "camera" {
apply_inverse = true;
camera_transform.render_from_camera
} else if coords_system == "world" {
AnimatedTransform::from_transform(&camera_transform.world_from_render)
} else {
return Err(anyhow!(
"{}: unknown coordinate system for GBufferFilm. (Expecting camera
or world",
loc
)
.into());
};
let film = GBufferFilmHost::new(
&film_base,
&output_from_render,
apply_inverse,
colorspace,
max_component_value,
write_fp16,
);
Ok(Film::GBuffer(film.device))
}
}