Continuing refactoring, deleted camera construction on host side
This commit is contained in:
parent
31106696bd
commit
5b4928e1aa
29 changed files with 393 additions and 574 deletions
|
|
@ -45,6 +45,74 @@ pub struct RealisticCamera {
|
|||
}
|
||||
|
||||
impl RealisticCamera {
|
||||
pub fn new(
|
||||
base: CameraBase,
|
||||
lens_params: &[Float],
|
||||
focus_distance: Float,
|
||||
set_aperture_diameter: Float,
|
||||
aperture_image: Ptr<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_interfaces: GVec<LensElementInterface> = gvec();
|
||||
|
||||
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_interfaces.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] =
|
||||
RealisticCamera::compute_exit_pupil_bounds(&element_interfaces, r0, r1);
|
||||
}
|
||||
|
||||
let n_elements = element_interfaces.len();
|
||||
|
||||
RealisticCamera {
|
||||
base,
|
||||
focus_distance,
|
||||
element_interfaces,
|
||||
n_elements,
|
||||
physical_extent,
|
||||
set_aperture_diameter,
|
||||
aperture_image,
|
||||
exit_pupil_bounds,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compute_cardinal_points(r_in: Ray, r_out: Ray) -> (Float, Float) {
|
||||
let tf = -r_out.o.x() / r_out.d.x();
|
||||
let tp = (r_in.o.x() - r_out.o.x()) / r_out.d.x();
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ use crate::utils::math::{wrap_equal_area_square, SquareMatrix};
|
|||
use crate::utils::sampling::VarianceEstimator;
|
||||
use crate::utils::transform::AnimatedTransform;
|
||||
use crate::utils::{gpu_array_from_fn, AtomicFloat};
|
||||
use crate::{Array2D, Float, Ptr};
|
||||
use crate::{gvec_with_capacity, Array2D, Float, Ptr};
|
||||
use num_traits::Float as NumFloat;
|
||||
|
||||
#[repr(C)]
|
||||
|
|
@ -50,6 +50,43 @@ impl Default for RGBPixel {
|
|||
}
|
||||
|
||||
impl RGBFilm {
|
||||
pub fn new(
|
||||
base: FilmBase,
|
||||
colorspace: &RGBColorSpace,
|
||||
max_component_value: Float,
|
||||
write_fp16: bool,
|
||||
) -> Self {
|
||||
let sensor_ptr = base.sensor;
|
||||
// TODO: This wont work on gpu, need to add check on host side
|
||||
if sensor_ptr.is_null() {
|
||||
panic!("Film must have a sensor");
|
||||
}
|
||||
let sensor = &*sensor_ptr;
|
||||
let filter_integral = base.filter.integral();
|
||||
let sensor_matrix = sensor.xyz_from_sensor_rgb;
|
||||
let output_rgbf_from_sensor_rgb = colorspace.rgb_from_xyz * sensor_matrix;
|
||||
|
||||
let width = base.pixel_bounds.p_max.x() - base.pixel_bounds.p_min.x();
|
||||
let height = base.pixel_bounds.p_max.y() - base.pixel_bounds.p_min.y();
|
||||
let count = (width * height) as usize;
|
||||
|
||||
let mut pixel_vec = gvec_with_capacity(count);
|
||||
for _ in 0..count {
|
||||
pixel_vec.push(RGBPixel::default());
|
||||
}
|
||||
|
||||
let pixels: Array2D<RGBPixel> = Array2D::new(base.pixel_bounds);
|
||||
|
||||
RGBFilm {
|
||||
base,
|
||||
max_component_value,
|
||||
write_fp16,
|
||||
filter_integral,
|
||||
output_rgbf_from_sensor_rgb,
|
||||
pixels,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn base(&self) -> &FilmBase {
|
||||
&self.base
|
||||
}
|
||||
|
|
@ -214,6 +251,37 @@ pub struct GBufferFilm {
|
|||
}
|
||||
|
||||
impl GBufferFilm {
|
||||
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);
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn base(&self) -> &FilmBase {
|
||||
&self.base
|
||||
}
|
||||
|
|
@ -351,24 +419,73 @@ impl Default for SpectralPixel {
|
|||
#[cfg_attr(target_os = "cuda", derive(Copy, Clone))]
|
||||
pub struct SpectralFilm {
|
||||
pub base: FilmBase,
|
||||
pub colorspace: RGBColorSpace,
|
||||
pub lambda_min: Float,
|
||||
pub lambda_max: Float,
|
||||
pub n_buckets: usize,
|
||||
pub max_component_value: Float,
|
||||
pub write_fp16: bool,
|
||||
pub filter_integral: Float,
|
||||
pub colorspace: RGBColorSpace,
|
||||
pub pixels: Array2D<SpectralPixel>,
|
||||
pub output_rgbf_from_sensor_rgb: SquareMatrix<Float, 3>,
|
||||
pub bucket_sums: *mut f64,
|
||||
pub weight_sums: *mut f64,
|
||||
pub bucket_splats: *mut AtomicFloat,
|
||||
pub bucket_sums: GVec<f64>,
|
||||
pub weight_sums: GVec<f64>,
|
||||
pub bucket_splats: GVec<AtomicFloat>,
|
||||
}
|
||||
|
||||
unsafe impl Send for SpectralFilm {}
|
||||
unsafe impl Sync for SpectralFilm {}
|
||||
|
||||
impl SpectralFilm {
|
||||
pub fn new(
|
||||
base: &FilmBase,
|
||||
lambda_min: Float,
|
||||
lambda_max: Float,
|
||||
n_buckets: usize,
|
||||
colorspace: &RGBColorSpace,
|
||||
max_component_value: Float,
|
||||
write_fp16: bool,
|
||||
) -> Self {
|
||||
let n_pixels = base.pixel_bounds.area() as usize;
|
||||
let total_buckets = n_pixels * n_buckets;
|
||||
|
||||
let bucket_sums = gvec_with_capacity(total_buckets);
|
||||
let weight_sums = gvec_with_capacity(total_buckets);
|
||||
|
||||
let mut bucket_splats = gvec_with_capacity(total_buckets);
|
||||
for _ in 0..total_buckets {
|
||||
bucket_splats.push(AtomicFloat::new(0.0));
|
||||
}
|
||||
|
||||
let mut pixels = Array2D::<SpectralPixel>::new(base.pixel_bounds);
|
||||
|
||||
for i in 0..n_pixels {
|
||||
let pixel = pixels.get_linear_mut(i);
|
||||
pixel.bucket_offset = i * n_buckets;
|
||||
}
|
||||
|
||||
SpectralFilm {
|
||||
base,
|
||||
colorspace: colorspace.clone(),
|
||||
lambda_min,
|
||||
lambda_max,
|
||||
n_buckets,
|
||||
max_component_value,
|
||||
write_fp16,
|
||||
filter_integral: base.filter.integral(),
|
||||
output_rgbf_from_sensor_rgb: SquareMatrix::identity(),
|
||||
|
||||
pixels: Array2D {
|
||||
values: pixels.values.as_mut_ptr(),
|
||||
extent: base.pixel_bounds,
|
||||
},
|
||||
|
||||
bucket_sums,
|
||||
weight_sums,
|
||||
bucket_splats,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn base(&self) -> &FilmBase {
|
||||
&self.base
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use crate::core::geometry::{Bounds2f, Bounds2i, Point2f, Point2i, Vector2f};
|
|||
use crate::filters::*;
|
||||
use crate::utils::math::{gaussian, gaussian_integral, lerp, sample_tent, windowed_sinc};
|
||||
use crate::utils::sampling::PiecewiseConstant2D;
|
||||
use crate::{DeviceArray2D, Float};
|
||||
use crate::{Array2D, Float};
|
||||
use enum_dispatch::enum_dispatch;
|
||||
|
||||
pub struct FilterSample {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use crate::core::color::{ColorEncoding, ColorEncodingTrait, LINEAR};
|
||||
use crate::core::geometry::{Bounds2f, Point2f, Point2fi, Point2i};
|
||||
use crate::utils::containers::DeviceArray2D;
|
||||
use crate::utils::math::{f16_to_f32_software, lerp, square};
|
||||
use crate::Float;
|
||||
use crate::GVec;
|
||||
|
|
|
|||
|
|
@ -1,19 +1,18 @@
|
|||
use enum_dispatch::enum_dispatch;
|
||||
|
||||
use crate::core::geometry::{
|
||||
Bounds3f, Frame, Point2f, Point3f, Point3i, Ray, Vector3f, VectorLike, spherical_direction,
|
||||
spherical_direction, Bounds3f, Frame, Point2f, Point3f, Point3i, Ray, Vector3f, VectorLike,
|
||||
};
|
||||
use crate::core::pbrt::{Float, INV_4_PI, PI};
|
||||
use crate::core::spectrum::{Spectrum, SpectrumTrait};
|
||||
use crate::spectra::{
|
||||
BlackbodySpectrum, DenselySampledSpectrum, LAMBDA_MAX, LAMBDA_MIN, RGBIlluminantSpectrum,
|
||||
RGBUnboundedSpectrum, SampledSpectrum, SampledWavelengths,
|
||||
BlackbodySpectrum, DenselySampledSpectrum, RGBIlluminantSpectrum, RGBUnboundedSpectrum,
|
||||
SampledSpectrum, SampledWavelengths, LAMBDA_MAX, LAMBDA_MIN,
|
||||
};
|
||||
use crate::utils::containers::SampledGrid;
|
||||
use crate::utils::math::{clamp, square};
|
||||
use crate::utils::ptr::Ptr;
|
||||
use crate::utils::rng::Rng;
|
||||
use crate::utils::transform::Transform;
|
||||
use crate::{gvec_with_capacity, GVec, Ptr};
|
||||
use enum_dispatch::enum_dispatch;
|
||||
use num_traits::Float as NumFloat;
|
||||
|
||||
#[repr(C)]
|
||||
|
|
@ -90,11 +89,11 @@ impl PhaseFunctionTrait for HGPhaseFunction {
|
|||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MajorantGrid {
|
||||
pub bounds: Bounds3f,
|
||||
pub res: Point3i,
|
||||
pub voxels: *mut Float,
|
||||
pub voxels: GVec<Float>,
|
||||
pub n_voxels: u32,
|
||||
}
|
||||
|
||||
|
|
@ -102,21 +101,21 @@ unsafe impl Send for MajorantGrid {}
|
|||
unsafe impl Sync for MajorantGrid {}
|
||||
|
||||
impl MajorantGrid {
|
||||
// #[cfg(not(target_os = "cuda"))]
|
||||
// pub fn new(bounds: Bounds3f, res: Point3i) -> Self {
|
||||
// let n_voxels = (res.x() * res.y() * res.z()) as usize;
|
||||
// let voxels = Vec::with_capacity(n_voxels);
|
||||
// Self {
|
||||
// bounds,
|
||||
// res,
|
||||
// voxels: voxels.as_ptr(),
|
||||
// n_voxels: n_voxels as u32,
|
||||
// }
|
||||
// }
|
||||
//
|
||||
#[cfg(not(target_os = "cuda"))]
|
||||
pub fn new(bounds: Bounds3f, res: Point3i) -> Self {
|
||||
let n_voxels = (res.x() * res.y() * res.z()) as usize;
|
||||
let voxels = gvec_with_capacity(n_voxels);
|
||||
Self {
|
||||
bounds,
|
||||
res,
|
||||
voxels,
|
||||
n_voxels: n_voxels as u32,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn is_valid(&self) -> bool {
|
||||
!self.voxels.is_null()
|
||||
!self.voxels.is_empty()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
|
@ -128,7 +127,7 @@ impl MajorantGrid {
|
|||
let idx = z * self.res.x() * self.res.y() + y * self.res.x() + x;
|
||||
|
||||
if idx >= 0 && (idx as u32) < self.n_voxels {
|
||||
unsafe { *self.voxels.add(idx as usize) }
|
||||
unsafe { *self.voxels.as_ptr().add(idx as usize) }
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
|
|
@ -143,7 +142,7 @@ impl MajorantGrid {
|
|||
let idx = x + self.res.x() * (y + self.res.y() * z);
|
||||
|
||||
unsafe {
|
||||
*self.voxels.add(idx as usize) = v;
|
||||
*self.voxels.as_ptr().add(idx as usize) = v;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use crate::utils::math::{
|
|||
clamp, encode_morton_2, inverse_radical_inverse, lerp, log2_int,
|
||||
owen_scrambled_radical_inverse, permutation_element, radical_inverse, round_up_pow2,
|
||||
scrambled_radical_inverse, sobol_interval_to_index, sobol_sample, BinaryPermuteScrambler,
|
||||
DeviceDigitPermutation, FastOwenScrambler, NoRandomizer, OwenScrambler, Scrambler,
|
||||
DigitPermutation, FastOwenScrambler, NoRandomizer, OwenScrambler, Scrambler,
|
||||
PRIME_TABLE_SIZE,
|
||||
};
|
||||
use crate::utils::rng::Rng;
|
||||
|
|
@ -100,7 +100,7 @@ pub struct HaltonSampler {
|
|||
pub mult_inverse: [u64; 2],
|
||||
pub halton_index: u64,
|
||||
pub dim: u32,
|
||||
pub digit_permutations: GVec<DeviceDigitPermutation>,
|
||||
pub digit_permutations: GVec<DigitPermutation>,
|
||||
}
|
||||
|
||||
#[allow(clippy::derivable_impls)]
|
||||
|
|
|
|||
|
|
@ -20,6 +20,22 @@ pub struct DistantLight {
|
|||
}
|
||||
|
||||
impl DistantLight {
|
||||
pub fn new(render_from_light: Transform, le: Spectrum, scale: Float) -> Self {
|
||||
let base = LightBase::new(
|
||||
LightType::DeltaDirection,
|
||||
render_from_light,
|
||||
MediumInterface::empty(),
|
||||
);
|
||||
let lemit = lookup_spectrum(&le);
|
||||
Self {
|
||||
base,
|
||||
lemit: Ptr::from(&lemit.device()),
|
||||
scale,
|
||||
scene_center: Point3f::default(),
|
||||
scene_radius: 0.,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sample_li_base(
|
||||
&self,
|
||||
ctx_p: Point3f,
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ use crate::spectra::{DenselySampledSpectrum, SampledSpectrum, SampledWavelengths
|
|||
use crate::spectra::{RGBColorSpace, RGBIlluminantSpectrum};
|
||||
use crate::utils::math::{clamp, equal_area_sphere_to_square, equal_area_square_to_sphere, square};
|
||||
use crate::utils::sampling::{
|
||||
AliasTable, DevicePiecewiseConstant2D, WindowedPiecewiseConstant2D,
|
||||
sample_uniform_sphere, uniform_sphere_pdf,
|
||||
sample_uniform_sphere, uniform_sphere_pdf, AliasTable, DevicePiecewiseConstant2D,
|
||||
WindowedPiecewiseConstant2D,
|
||||
};
|
||||
use crate::utils::{Ptr, Transform};
|
||||
use crate::{Float, PI};
|
||||
|
|
@ -35,6 +35,27 @@ pub struct UniformInfiniteLight {
|
|||
unsafe impl Send for UniformInfiniteLight {}
|
||||
unsafe impl Sync for UniformInfiniteLight {}
|
||||
|
||||
impl UniformInfiniteLight {
|
||||
pub fn new(
|
||||
render_from_light: Transform,
|
||||
scale: Float,
|
||||
lemit: Ptr<DenselySampledSpectrum>,
|
||||
) -> Self {
|
||||
let base = LightBase::new(
|
||||
LightType::Infinite,
|
||||
render_from_light,
|
||||
MediumInterface::default(),
|
||||
);
|
||||
Self {
|
||||
base,
|
||||
lemit,
|
||||
scale,
|
||||
scene_center: Point3f::default(),
|
||||
scene_radius: 0.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LightTrait for UniformInfiniteLight {
|
||||
fn base(&self) -> &LightBase {
|
||||
&self.base
|
||||
|
|
@ -116,8 +137,8 @@ pub struct ImageInfiniteLight {
|
|||
pub base: LightBase,
|
||||
pub image: Ptr<Image>,
|
||||
pub image_color_space: Ptr<RGBColorSpace>,
|
||||
pub distrib: Ptr<DevicePiecewiseConstant2D>,
|
||||
pub compensated_distrib: Ptr<DevicePiecewiseConstant2D>,
|
||||
pub distrib: Ptr<PiecewiseConstant2D>,
|
||||
pub compensated_distrib: Ptr<PiecewiseConstant2D>,
|
||||
pub scale: Float,
|
||||
pub scene_radius: Float,
|
||||
pub scene_center: Point3f,
|
||||
|
|
@ -127,14 +148,35 @@ unsafe impl Send for ImageInfiniteLight {}
|
|||
unsafe impl Sync for ImageInfiniteLight {}
|
||||
|
||||
impl ImageInfiniteLight {
|
||||
pub fn new(
|
||||
render_from_light: Transform,
|
||||
scale: Float,
|
||||
image: Ptr<HostImage>,
|
||||
image_color_space: Ptr<RGBColorSpace>,
|
||||
distrib: Ptr<PiecewiseConstant2D>,
|
||||
compensated_distrib: Ptr<PiecewiseConstant2D>,
|
||||
) -> Self {
|
||||
let base = LightBase::new(
|
||||
LightType::Infinite,
|
||||
render_from_light,
|
||||
MediumInterface::default(),
|
||||
);
|
||||
Self {
|
||||
base,
|
||||
image,
|
||||
image_color_space,
|
||||
scale,
|
||||
distrib,
|
||||
compensated_distrib,
|
||||
scene_center: Point3f::default(),
|
||||
scene_radius: 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
fn image_le(&self, uv: Point2f, lambda: &SampledWavelengths) -> SampledSpectrum {
|
||||
let mut rgb = RGB::default();
|
||||
for c in 0..3 {
|
||||
rgb[c] = self.image.lookup_nearest_channel_with_wrap(
|
||||
uv,
|
||||
c,
|
||||
WrapMode::OctahedralSphere.into(),
|
||||
);
|
||||
rgb[c] = self.image.get_ch(uv, c, WrapMode::OctahedralSphere.into());
|
||||
}
|
||||
let spec = RGBIlluminantSpectrum::new(&self.image_color_space, rgb.clamp_zero());
|
||||
self.scale * spec.sample(lambda)
|
||||
|
|
@ -261,6 +303,33 @@ pub struct PortalInfiniteLight {
|
|||
}
|
||||
|
||||
impl PortalInfiniteLight {
|
||||
pub fn new(
|
||||
render_from_light: Transform,
|
||||
scale: Float,
|
||||
image: Ptr<HostImage>,
|
||||
image_color_space: Ptr<RGBColorSpace>,
|
||||
portal: [Point3f; 4],
|
||||
portal_frame: Frame,
|
||||
distribution: Ptr<WindowedPiecewiseConstant2D>,
|
||||
) -> Self {
|
||||
let base = LightBase::new(
|
||||
LightType::Infinite,
|
||||
render_from_light,
|
||||
MediumInterface::default(),
|
||||
);
|
||||
Self {
|
||||
base,
|
||||
image,
|
||||
image_color_space,
|
||||
scale,
|
||||
portal,
|
||||
portal_frame,
|
||||
distribution: *distribution,
|
||||
scene_center: Point3f::default(),
|
||||
scene_radius: 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn image_lookup(&self, uv: Point2f, lambda: &SampledWavelengths) -> SampledSpectrum {
|
||||
let mut rgb = RGB::default();
|
||||
for c in 0..3 {
|
||||
|
|
|
|||
|
|
@ -7,8 +7,7 @@ use crate::core::light::{
|
|||
};
|
||||
use crate::core::spectrum::SpectrumTrait;
|
||||
use crate::spectra::{DenselySampledSpectrum, SampledSpectrum, SampledWavelengths};
|
||||
use crate::utils::Ptr;
|
||||
use crate::{Float, PI};
|
||||
use crate::{Float, PI, Ptr, Transform};
|
||||
use num_traits::Float as NumFloat;
|
||||
|
||||
#[repr(C)]
|
||||
|
|
@ -19,6 +18,25 @@ pub struct PointLight {
|
|||
pub i: Ptr<DenselySampledSpectrum>,
|
||||
}
|
||||
|
||||
impl PointLight {
|
||||
pub fn new(
|
||||
render_from_light: Transform,
|
||||
medium_interface: MediumInterface,
|
||||
le: Spectrum,
|
||||
scale: Float,
|
||||
) -> Self {
|
||||
let base = LightBase::new(
|
||||
LightType::DeltaPosition,
|
||||
render_from_light,
|
||||
medium_interface,
|
||||
);
|
||||
let iemit = lookup_spectrum(&le);
|
||||
let i = Ptr::from(&iemit.device());
|
||||
|
||||
Self { base, scale, i }
|
||||
}
|
||||
}
|
||||
|
||||
impl LightTrait for PointLight {
|
||||
fn base(&self) -> &LightBase {
|
||||
&self.base
|
||||
|
|
|
|||
|
|
@ -198,12 +198,12 @@ pub enum LightSampler {
|
|||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct UniformLightSampler {
|
||||
lights: *const Light,
|
||||
lights: Ptr<Light>,
|
||||
lights_len: u32,
|
||||
}
|
||||
|
||||
impl UniformLightSampler {
|
||||
pub fn new(lights: *const Light, lights_len: u32) -> Self {
|
||||
pub fn new(lights: Ptr<Light>, lights_len: u32) -> Self {
|
||||
Self { lights, lights_len }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ use crate::core::interaction::{Interaction, InteractionBase, InteractionTrait, S
|
|||
use crate::core::light::{LightBase, LightBounds, LightLiSample, LightSampleContext, LightTrait};
|
||||
use crate::core::spectrum::SpectrumTrait;
|
||||
use crate::spectra::{DenselySampledSpectrum, SampledSpectrum, SampledWavelengths};
|
||||
use crate::utils::Ptr;
|
||||
use crate::{Float, PI};
|
||||
use crate::{Float, PI, Ptr, Transform};
|
||||
use num_traits::Float as NumFloat;
|
||||
|
||||
#[repr(C)]
|
||||
|
|
@ -20,6 +19,31 @@ pub struct SpotLight {
|
|||
}
|
||||
|
||||
impl SpotLight {
|
||||
pub fn new(
|
||||
render_from_light: Transform,
|
||||
_medium_interface: MediumInterface,
|
||||
le: Spectrum,
|
||||
scale: shared::Float,
|
||||
cos_falloff_start: Float,
|
||||
total_width: Float,
|
||||
) -> Self {
|
||||
let base = LightBase::new(
|
||||
LightType::DeltaPosition,
|
||||
render_from_light,
|
||||
MediumInterface::empty(),
|
||||
);
|
||||
|
||||
let i = lookup_spectrum(&le);
|
||||
let iemit = Ptr::from(&i.device());
|
||||
Self {
|
||||
base,
|
||||
iemit,
|
||||
scale,
|
||||
cos_falloff_end: radians(total_width).cos(),
|
||||
cos_falloff_start: radians(cos_falloff_start).cos(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn i(&self, w: Vector3f, lambda: &SampledWavelengths) -> SampledSpectrum {
|
||||
let cos_theta = w.z(); // assuming normalized in light space
|
||||
let falloff = crate::utils::math::smooth_step(
|
||||
|
|
|
|||
|
|
@ -821,7 +821,7 @@ impl DigitPermutation {
|
|||
pub fn scrambled_radical_inverse(
|
||||
base_index: u32,
|
||||
mut a: u64,
|
||||
perm: &DeviceDigitPermutation,
|
||||
perm: &DigitPermutation,
|
||||
) -> Float {
|
||||
let base = PRIMES[base_index as usize] as u64;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
pub mod perspective;
|
||||
pub mod realistic;
|
||||
pub mod spherical;
|
||||
|
|
@ -1 +0,0 @@
|
|||
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
use crate::core::image::Image;
|
||||
use shared::cameras::{EXIT_PUPIL_SAMPLES, LensElementInterface, RealisticCamera};
|
||||
use shared::core::camera::CameraBase;
|
||||
use shared::core::geometry::{Bounds2f, Point2f};
|
||||
use shared::utils::math::square;
|
||||
use shared::{Float, Ptr};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct RealisticCameraData {
|
||||
aperture_image: Arc<Image>,
|
||||
element_interfaces: Vec<LensElementInterface>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RealisticCameraHost {
|
||||
device: RealisticCamera,
|
||||
data: RealisticCameraData,
|
||||
}
|
||||
|
||||
impl RealisticCameraHost {
|
||||
pub fn device(&self) -> RealisticCamera {
|
||||
self.device
|
||||
}
|
||||
|
||||
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_interfaces: 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_interfaces.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] =
|
||||
RealisticCamera::compute_exit_pupil_bounds(&element_interfaces, r0, r1);
|
||||
}
|
||||
|
||||
let n_elements = element_interfaces.len();
|
||||
|
||||
let data = RealisticCameraData {
|
||||
element_interfaces: element_interfaces.clone(),
|
||||
aperture_image: aperture_image.clone(),
|
||||
};
|
||||
|
||||
let device = RealisticCamera {
|
||||
base,
|
||||
focus_distance,
|
||||
element_interfaces: Ptr::from(element_interfaces.as_ptr()),
|
||||
n_elements,
|
||||
physical_extent,
|
||||
set_aperture_diameter,
|
||||
aperture_image: Ptr::from(aperture_image.device()),
|
||||
exit_pupil_bounds,
|
||||
};
|
||||
|
||||
Self { device, data }
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
|
||||
|
|
@ -1,9 +1,8 @@
|
|||
use crate::cameras::realistic::RealisticCameraHost;
|
||||
use crate::core::image::ImageMetadata;
|
||||
use crate::core::image::{Image, ImageIO};
|
||||
use crate::globals::get_options;
|
||||
use crate::utils::read_float_file;
|
||||
use crate::utils::{Arena, FileLoc, ParameterDictionary};
|
||||
use crate::{Arena, FileLoc, ParameterDictionary};
|
||||
use anyhow::{anyhow, Result};
|
||||
use shared::cameras::*;
|
||||
use shared::core::camera::{Camera, CameraBase, CameraTrait, CameraTransform};
|
||||
|
|
@ -13,8 +12,7 @@ use shared::core::geometry::{Bounds2f, Point2f, Point2i, Vector2f, Vector3f};
|
|||
use shared::core::image::PixelFormat;
|
||||
use shared::core::medium::Medium;
|
||||
use shared::utils::math::square;
|
||||
use shared::Ptr;
|
||||
use shared::{Float, PI};
|
||||
use shared::{Float, Ptr, PI};
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
|
||||
|
|
@ -380,16 +378,16 @@ impl CameraFactory for Camera {
|
|||
}
|
||||
}
|
||||
|
||||
let camera = RealisticCameraHost::new(
|
||||
let camera = RealisticCamera::new(
|
||||
base,
|
||||
&lens_params,
|
||||
focal_distance,
|
||||
aperture_diameter,
|
||||
Arc::from(aperture_image.unwrap()),
|
||||
Ptr::from(&*aperture_image.unwrap()),
|
||||
);
|
||||
|
||||
arena.alloc(camera);
|
||||
Ok(Camera::Realistic(camera.device()))
|
||||
Ok(Camera::Realistic(camera))
|
||||
}
|
||||
"spherical" => {
|
||||
let _full_res = film.full_resolution();
|
||||
|
|
|
|||
|
|
@ -2,30 +2,8 @@ use shared::core::geometry::{Bounds3f, Point3i};
|
|||
use shared::core::medium::{GridMedium, HGPhaseFunction, HomogeneousMedium, RGBGridMedium};
|
||||
use shared::core::spectrum::{Spectrum, SpectrumTrait};
|
||||
use shared::spectra::{RGBIlluminantSpectrum, RGBUnboundedSpectrum, DenselySampledSpectrum};
|
||||
use shared::utils::Transform;
|
||||
use shared::utils::containers::SampledGrid;
|
||||
use shared::{Float, core::medium::MajorantGrid};
|
||||
|
||||
pub struct MajorantGridHost {
|
||||
pub device: MajorantGrid,
|
||||
voxels: Vec<Float>,
|
||||
}
|
||||
|
||||
impl MajorantGridHost {
|
||||
pub fn new(bounds: Bounds3f, res: Point3i) -> Self {
|
||||
let n = (res.x() * res.y() * res.z()) as usize;
|
||||
let voxels = vec![0.0; n];
|
||||
|
||||
let device = MajorantGrid {
|
||||
bounds,
|
||||
res,
|
||||
voxels: std::ptr::null_mut(),
|
||||
n_voxels: n as u32,
|
||||
};
|
||||
|
||||
Self { device, voxels }
|
||||
}
|
||||
}
|
||||
use shared::{Float, Transform, core::medium::MajorantGrid};
|
||||
|
||||
pub trait RGBGridMediumCreator {
|
||||
fn new(
|
||||
|
|
@ -52,7 +30,7 @@ impl RGBGridMediumCreator for RGBGridMedium {
|
|||
le_grid: SampledGrid<RGBIlluminantSpectrum>,
|
||||
le_scale: Float,
|
||||
) -> Self {
|
||||
let mut majorant_grid = MajorantGridHost::new(*bounds, Point3i::new(16, 16, 16)).device;
|
||||
let mut majorant_grid = MajorantGrid::new(*bounds, Point3i::new(16, 16, 16));
|
||||
for z in 0..majorant_grid.res.x() {
|
||||
for y in 0..majorant_grid.res.y() {
|
||||
for x in 0..majorant_grid.res.x() {
|
||||
|
|
@ -116,7 +94,7 @@ impl GridMediumCreator for GridMedium {
|
|||
|
||||
let le_spec = DenselySampledSpectrum::from_spectrum(le);
|
||||
|
||||
let mut majorant_grid = MajorantGridHost::new(*bounds, Point3i::new(16, 16, 16)).device;
|
||||
let mut majorant_grid = MajorantGrid::new(*bounds, Point3i::new(16, 16, 16)).device;
|
||||
let is_emissive = if temperature_grid.is_some() {
|
||||
true
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use crate::core::texture::{FloatTexture, SpectrumTexture};
|
|||
use crate::utils::parallel::{run_async, AsyncJob};
|
||||
use crate::utils::parameters::{NamedTextures, ParameterDictionary, TextureParameterDictionary};
|
||||
use crate::utils::resolve_filename;
|
||||
use crate::{Arena, DeviceRepr, FileLoc};
|
||||
use crate::{Arena, FileLoc};
|
||||
use anyhow::{anyhow, Result};
|
||||
use parking_lot::Mutex;
|
||||
use shared::core::camera::{Camera, CameraTransform};
|
||||
|
|
|
|||
|
|
@ -8,44 +8,6 @@ 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(
|
||||
|
|
@ -85,7 +47,7 @@ impl CreateFilm for GBufferFilm {
|
|||
.into());
|
||||
};
|
||||
|
||||
let film = GBufferFilmHost::new(
|
||||
let film = GBufferFilm::new(
|
||||
&film_base,
|
||||
&output_from_render,
|
||||
apply_inverse,
|
||||
|
|
@ -94,6 +56,6 @@ impl CreateFilm for GBufferFilm {
|
|||
write_fp16,
|
||||
);
|
||||
|
||||
Ok(Film::GBuffer(film.device))
|
||||
Ok(Film::GBuffer(film))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,58 +8,6 @@ use shared::core::film::{Film, FilmBase, RGBFilm, RGBPixel};
|
|||
use shared::core::filter::FilterTrait;
|
||||
use shared::spectra::RGBColorSpace;
|
||||
|
||||
struct RGBFilmStorage {
|
||||
pixels: Array2D<RGBPixel>,
|
||||
}
|
||||
|
||||
pub struct RGBFilmHost {
|
||||
pub device: RGBFilm,
|
||||
storage: RGBFilmStorage,
|
||||
}
|
||||
|
||||
impl RGBFilmHost {
|
||||
pub fn new(
|
||||
base: FilmBase,
|
||||
colorspace: &RGBColorSpace,
|
||||
max_component_value: Float,
|
||||
write_fp16: bool,
|
||||
) -> Self {
|
||||
let sensor_ptr = base.sensor;
|
||||
if sensor_ptr.is_null() {
|
||||
panic!("Film must have a sensor");
|
||||
}
|
||||
let sensor = &*sensor_ptr;
|
||||
let filter_integral = base.filter.integral();
|
||||
let sensor_matrix = sensor.xyz_from_sensor_rgb;
|
||||
let output_rgbf_from_sensor_rgb = colorspace.rgb_from_xyz * sensor_matrix;
|
||||
|
||||
let width = base.pixel_bounds.p_max.x() - base.pixel_bounds.p_min.x();
|
||||
let height = base.pixel_bounds.p_max.y() - base.pixel_bounds.p_min.y();
|
||||
let count = (width * height) as usize;
|
||||
|
||||
let mut pixel_vec = Vec::with_capacity(count);
|
||||
for _ in 0..count {
|
||||
pixel_vec.push(RGBPixel::default());
|
||||
}
|
||||
|
||||
let pixels: Array2D<RGBPixel> = Array2D::new(base.pixel_bounds);
|
||||
|
||||
let device_pixels = pixels.device.clone();
|
||||
let storage = RGBFilmStorage { pixels };
|
||||
|
||||
let device = RGBFilm {
|
||||
base,
|
||||
max_component_value,
|
||||
write_fp16,
|
||||
filter_integral,
|
||||
output_rgbf_from_sensor_rgb,
|
||||
pixels: device_pixels,
|
||||
};
|
||||
|
||||
Self { device, storage }
|
||||
}
|
||||
}
|
||||
|
||||
impl CreateFilm for RGBFilm {
|
||||
fn create(
|
||||
params: &ParameterDictionary,
|
||||
|
|
@ -74,7 +22,7 @@ impl CreateFilm for RGBFilm {
|
|||
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 film = RGBFilmHost::new(film_base, &colorspace, max_component_value, write_fp16);
|
||||
Ok(Film::RGB(film.device))
|
||||
let film = RGBFilm::new(film_base, &colorspace, max_component_value, write_fp16);
|
||||
Ok(Film::RGB(film))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,91 +1,15 @@
|
|||
use super::*;
|
||||
use crate::core::film::{CreateFilmBase, PixelSensor};
|
||||
use crate::utils::containers::Array2D;
|
||||
use crate::{Arena, FileLoc, ParameterDictionary};
|
||||
use anyhow::{Result, anyhow};
|
||||
use shared::Float;
|
||||
use shared::core::camera::CameraTransform;
|
||||
use shared::core::film::{FilmBase, SpectralFilm, SpectralPixel};
|
||||
use shared::core::film::{FilmBase, SpectralFilm};
|
||||
use shared::core::filter::FilterTrait;
|
||||
use shared::spectra::{LAMBDA_MAX, LAMBDA_MIN, RGBColorSpace};
|
||||
use shared::utils::AtomicFloat;
|
||||
use shared::utils::containers::Array2D;
|
||||
use shared::spectra::{LAMBDA_MAX, LAMBDA_MIN};
|
||||
use shared::utils::math::SquareMatrix;
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
|
||||
struct SpectralFilmStorage {
|
||||
pixels: Array2D<SpectralPixel>,
|
||||
bucket_sums: Vec<f64>,
|
||||
weight_sums: Vec<f64>,
|
||||
bucket_splats: Vec<AtomicFloat>,
|
||||
}
|
||||
|
||||
pub struct SpectralFilmHost {
|
||||
pub device: SpectralFilm,
|
||||
storage: Arc<SpectralFilmStorage>,
|
||||
}
|
||||
|
||||
impl SpectralFilmHost {
|
||||
pub fn new(
|
||||
base: &FilmBase,
|
||||
lambda_min: Float,
|
||||
lambda_max: Float,
|
||||
n_buckets: usize,
|
||||
colorspace: &RGBColorSpace,
|
||||
max_component_value: Float,
|
||||
write_fp16: bool,
|
||||
) -> Self {
|
||||
let n_pixels = base.pixel_bounds.area() as usize;
|
||||
let total_buckets = n_pixels * n_buckets;
|
||||
|
||||
let bucket_sums = vec![0.0; total_buckets];
|
||||
let weight_sums = vec![0.0; total_buckets];
|
||||
|
||||
let mut bucket_splats = Vec::with_capacity(total_buckets);
|
||||
for _ in 0..total_buckets {
|
||||
bucket_splats.push(AtomicFloat::new(0.0));
|
||||
}
|
||||
|
||||
let mut pixels = Array2D::<SpectralPixel>::new(base.pixel_bounds);
|
||||
|
||||
for i in 0..n_pixels {
|
||||
let pixel = pixels.get_linear_mut(i);
|
||||
pixel.bucket_offset = i * n_buckets;
|
||||
}
|
||||
|
||||
let storage = Arc::new(SpectralFilmStorage {
|
||||
pixels: pixels.device,
|
||||
bucket_sums,
|
||||
weight_sums,
|
||||
bucket_splats,
|
||||
});
|
||||
|
||||
let device = SpectralFilm {
|
||||
base: *base,
|
||||
colorspace: colorspace.clone(),
|
||||
lambda_min,
|
||||
lambda_max,
|
||||
n_buckets,
|
||||
max_component_value,
|
||||
write_fp16,
|
||||
filter_integral: base.filter.integral(),
|
||||
output_rgbf_from_sensor_rgb: SquareMatrix::identity(),
|
||||
|
||||
pixels: Array2D {
|
||||
values: pixels.values.as_mut_ptr(),
|
||||
extent: base.pixel_bounds,
|
||||
stride: base.pixel_bounds.p_max.x() - base.pixel_bounds.p_min.x(),
|
||||
},
|
||||
|
||||
bucket_sums: storage.bucket_sums.as_ptr() as *mut f64,
|
||||
weight_sums: storage.weight_sums.as_ptr() as *mut f64,
|
||||
bucket_splats: storage.bucket_splats.as_ptr() as *mut AtomicFloat,
|
||||
};
|
||||
|
||||
Self { device, storage }
|
||||
}
|
||||
}
|
||||
|
||||
impl CreateFilm for SpectralFilm {
|
||||
fn create(
|
||||
|
|
@ -96,6 +20,7 @@ impl CreateFilm for SpectralFilm {
|
|||
loc: &FileLoc,
|
||||
_arena: &Arena,
|
||||
) -> Result<Film> {
|
||||
// Missing default illuminant, use srgb
|
||||
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)?;
|
||||
|
|
@ -117,7 +42,7 @@ impl CreateFilm for SpectralFilm {
|
|||
));
|
||||
}
|
||||
|
||||
let film = SpectralFilmHost::new(
|
||||
let film = SpectralFilm::new(
|
||||
&film_base,
|
||||
lambda_min,
|
||||
lambda_max,
|
||||
|
|
@ -127,6 +52,6 @@ impl CreateFilm for SpectralFilm {
|
|||
write_fp16,
|
||||
);
|
||||
|
||||
Ok(Film::Spectral(film.device))
|
||||
Ok(Film::Spectral(film))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#![feature(f16)]
|
||||
#[allow(dead_code)]
|
||||
pub mod cameras;
|
||||
pub mod core;
|
||||
pub mod films;
|
||||
pub mod filters;
|
||||
|
|
|
|||
|
|
@ -14,28 +14,6 @@ use shared::lights::DistantLight;
|
|||
use shared::spectra::RGBColorSpace;
|
||||
use shared::utils::{Ptr, Transform};
|
||||
|
||||
pub trait CreateDistantLight {
|
||||
fn new(render_from_light: Transform, le: Spectrum, scale: Float) -> Self;
|
||||
}
|
||||
|
||||
impl CreateDistantLight for DistantLight {
|
||||
fn new(render_from_light: Transform, le: Spectrum, scale: Float) -> Self {
|
||||
let base = LightBase::new(
|
||||
LightType::DeltaDirection,
|
||||
render_from_light,
|
||||
MediumInterface::empty(),
|
||||
);
|
||||
let lemit = lookup_spectrum(&le);
|
||||
Self {
|
||||
base,
|
||||
lemit: Ptr::from(&lemit.device()),
|
||||
scale,
|
||||
scene_center: Point3f::default(),
|
||||
scene_radius: 0.,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create(
|
||||
render_from_light: Transform,
|
||||
_medium: Option<Medium>,
|
||||
|
|
|
|||
|
|
@ -21,106 +21,6 @@ use shared::utils::sampling::{PiecewiseConstant2D, WindowedPiecewiseConstant2D};
|
|||
use shared::{Float, Ptr, Transform, PI};
|
||||
use std::path::Path;
|
||||
|
||||
pub trait CreateImageInfiniteLight {
|
||||
fn new(
|
||||
render_from_light: Transform,
|
||||
scale: Float,
|
||||
image: Ptr<HostImage>,
|
||||
image_color_space: Ptr<RGBColorSpace>,
|
||||
distrib: Ptr<PiecewiseConstant2D>,
|
||||
compensated_distrib: Ptr<PiecewiseConstant2D>,
|
||||
) -> Self;
|
||||
}
|
||||
|
||||
impl CreateImageInfiniteLight for ImageInfiniteLight {
|
||||
fn new(
|
||||
render_from_light: Transform,
|
||||
scale: Float,
|
||||
image: Ptr<HostImage>,
|
||||
image_color_space: Ptr<RGBColorSpace>,
|
||||
distrib: Ptr<PiecewiseConstant2D>,
|
||||
compensated_distrib: Ptr<PiecewiseConstant2D>,
|
||||
) -> Self {
|
||||
let base = LightBase::new(
|
||||
LightType::Infinite,
|
||||
render_from_light,
|
||||
MediumInterface::default(),
|
||||
);
|
||||
Self {
|
||||
base,
|
||||
image,
|
||||
image_color_space,
|
||||
scale,
|
||||
distrib,
|
||||
compensated_distrib,
|
||||
scene_center: Point3f::default(),
|
||||
scene_radius: 0.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait CreatePortalInfiniteLight {
|
||||
fn new(
|
||||
render_from_light: Transform,
|
||||
scale: Float,
|
||||
image: Ptr<HostImage>,
|
||||
image_color_space: Ptr<RGBColorSpace>,
|
||||
portal: [Point3f; 4],
|
||||
portal_frame: Frame,
|
||||
distribution: Ptr<WindowedPiecewiseConstant2D>,
|
||||
) -> Self;
|
||||
}
|
||||
|
||||
impl CreatePortalInfiniteLight for PortalInfiniteLight {
|
||||
fn new(
|
||||
render_from_light: Transform,
|
||||
scale: Float,
|
||||
image: Ptr<HostImage>,
|
||||
image_color_space: Ptr<RGBColorSpace>,
|
||||
portal: [Point3f; 4],
|
||||
portal_frame: Frame,
|
||||
distribution: Ptr<WindowedPiecewiseConstant2D>,
|
||||
) -> Self {
|
||||
let base = LightBase::new(
|
||||
LightType::Infinite,
|
||||
render_from_light,
|
||||
MediumInterface::default(),
|
||||
);
|
||||
Self {
|
||||
base,
|
||||
image,
|
||||
image_color_space,
|
||||
scale,
|
||||
portal,
|
||||
portal_frame,
|
||||
distribution: *distribution,
|
||||
scene_center: Point3f::default(),
|
||||
scene_radius: 0.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait CreateUniformInfiniteLight {
|
||||
fn new(render_from_light: Transform, scale: Float, lemit: Ptr<DenselySampledSpectrum>) -> Self;
|
||||
}
|
||||
|
||||
impl CreateUniformInfiniteLight for UniformInfiniteLight {
|
||||
fn new(render_from_light: Transform, scale: Float, lemit: Ptr<DenselySampledSpectrum>) -> Self {
|
||||
let base = LightBase::new(
|
||||
LightType::Infinite,
|
||||
render_from_light,
|
||||
MediumInterface::default(),
|
||||
);
|
||||
Self {
|
||||
base,
|
||||
lemit,
|
||||
scale,
|
||||
scene_center: Point3f::default(),
|
||||
scene_radius: 0.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create(
|
||||
render_from_light: Transform,
|
||||
_medium: Option<Medium>,
|
||||
|
|
|
|||
|
|
@ -6,10 +6,3 @@ pub mod point;
|
|||
pub mod projection;
|
||||
pub mod sampler;
|
||||
pub mod spot;
|
||||
|
||||
pub use distant::CreateDistantLight;
|
||||
pub use infinite::{
|
||||
CreateImageInfiniteLight, CreatePortalInfiniteLight, CreateUniformInfiniteLight,
|
||||
};
|
||||
pub use point::CreatePointLight;
|
||||
pub use spot::CreateSpotLight;
|
||||
|
|
|
|||
|
|
@ -11,36 +11,8 @@ use shared::core::spectrum::Spectrum;
|
|||
use shared::core::texture::SpectrumType;
|
||||
use shared::lights::PointLight;
|
||||
use shared::spectra::RGBColorSpace;
|
||||
use shared::utils::{Ptr, Transform};
|
||||
use shared::{Float, PI};
|
||||
use shared::{Float, PI, Ptr, Transform};
|
||||
|
||||
pub trait CreatePointLight {
|
||||
fn new(
|
||||
render_from_light: Transform,
|
||||
medium_interface: MediumInterface,
|
||||
le: Spectrum,
|
||||
scale: Float,
|
||||
) -> Self;
|
||||
}
|
||||
|
||||
impl CreatePointLight for PointLight {
|
||||
fn new(
|
||||
render_from_light: Transform,
|
||||
medium_interface: MediumInterface,
|
||||
le: Spectrum,
|
||||
scale: Float,
|
||||
) -> Self {
|
||||
let base = LightBase::new(
|
||||
LightType::DeltaPosition,
|
||||
render_from_light,
|
||||
medium_interface,
|
||||
);
|
||||
let iemit = lookup_spectrum(&le);
|
||||
let i = Ptr::from(&iemit.device());
|
||||
|
||||
Self { base, scale, i }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create(
|
||||
render_from_light: Transform,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::utils::sampling::AliasTableHost;
|
||||
use crate::Arena;
|
||||
use shared::core::light::{Light, LightTrait};
|
||||
use shared::lights::sampler::PowerLightSampler;
|
||||
use shared::utils::sampling::AliasTable;
|
||||
use shared::spectra::{SampledSpectrum, SampledWavelengths};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
|
@ -9,7 +9,7 @@ use std::sync::Arc;
|
|||
pub struct PowerSamplerHost {
|
||||
pub lights: Vec<Arc<Light>>,
|
||||
pub light_to_index: HashMap<usize, usize>,
|
||||
pub alias_table: AliasTableHost,
|
||||
pub alias_table: AliasTable,
|
||||
}
|
||||
|
||||
impl PowerSamplerHost {
|
||||
|
|
@ -18,7 +18,7 @@ impl PowerSamplerHost {
|
|||
return Self {
|
||||
lights: Vec::new(),
|
||||
light_to_index: HashMap::new(),
|
||||
alias_table: AliasTableHost::new(&[]),
|
||||
alias_table: AliasTable::new(&[]),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ impl PowerSamplerHost {
|
|||
light_power.push(phi.average());
|
||||
}
|
||||
|
||||
let alias_table = AliasTableHost::new(&light_power);
|
||||
let alias_table = AliasTable::new(&light_power);
|
||||
|
||||
Self {
|
||||
lights: lights_vec,
|
||||
|
|
@ -46,16 +46,15 @@ impl PowerSamplerHost {
|
|||
alias_table,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_device(&self, arena: &Arena) -> PowerLightSampler {
|
||||
let device_lights: Vec<Light> = self.lights.iter().map(|l| (**l).clone()).collect();
|
||||
let (lights_ptr, _) = arena.alloc_slice(&device_lights);
|
||||
let alias_device = self.alias_table.to_device(arena);
|
||||
|
||||
PowerLightSampler {
|
||||
lights: lights_ptr,
|
||||
lights_len: self.lights.len() as u32,
|
||||
alias_table: alias_device,
|
||||
}
|
||||
}
|
||||
// pub fn to_device(&self, arena: &Arena) -> PowerLightSampler {
|
||||
// let device_lights: Vec<Light> = self.lights.iter().map(|l| (**l).clone()).collect();
|
||||
// let (lights_ptr, _) = arena.alloc_slice(&device_lights);
|
||||
// let alias_device = self.alias_table.to_device(arena);
|
||||
//
|
||||
// PowerLightSampler {
|
||||
// lights: lights_ptr,
|
||||
// lights_len: self.lights.len() as u32,
|
||||
// alias_table: alias_device,
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,45 +13,7 @@ use shared::lights::SpotLight;
|
|||
use shared::spectra::RGBColorSpace;
|
||||
use shared::utils::math::radians;
|
||||
use shared::utils::{Ptr, Transform};
|
||||
use shared::{Float, PI};
|
||||
|
||||
pub trait CreateSpotLight {
|
||||
fn new(
|
||||
render_from_light: Transform,
|
||||
medium_interface: MediumInterface,
|
||||
le: Spectrum,
|
||||
scale: shared::Float,
|
||||
cos_falloff_start: Float,
|
||||
total_width: Float,
|
||||
) -> Self;
|
||||
}
|
||||
|
||||
impl CreateSpotLight for SpotLight {
|
||||
fn new(
|
||||
render_from_light: Transform,
|
||||
_medium_interface: MediumInterface,
|
||||
le: Spectrum,
|
||||
scale: shared::Float,
|
||||
cos_falloff_start: Float,
|
||||
total_width: Float,
|
||||
) -> Self {
|
||||
let base = LightBase::new(
|
||||
LightType::DeltaPosition,
|
||||
render_from_light,
|
||||
MediumInterface::empty(),
|
||||
);
|
||||
|
||||
let i = lookup_spectrum(&le);
|
||||
let iemit = Ptr::from(&i.device());
|
||||
Self {
|
||||
base,
|
||||
iemit,
|
||||
scale,
|
||||
cos_falloff_end: radians(total_width).cos(),
|
||||
cos_falloff_start: radians(cos_falloff_start).cos(),
|
||||
}
|
||||
}
|
||||
}
|
||||
use shared::{Float, PI, Ptr, Transform};
|
||||
|
||||
pub fn create(
|
||||
render_from_light: Transform,
|
||||
|
|
|
|||
Loading…
Reference in a new issue