99 lines
3.3 KiB
Rust
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))
|
|
}
|
|
}
|