From 5b4928e1aa7f79c4d8c81fdcda7464e81c3c20da Mon Sep 17 00:00:00 2001 From: Wito Wiala Date: Tue, 19 May 2026 01:44:38 +0100 Subject: [PATCH] Continuing refactoring, deleted camera construction on host side --- shared/src/cameras/realistic.rs | 68 +++++++++++++++++ shared/src/core/film.rs | 127 ++++++++++++++++++++++++++++++-- shared/src/core/filter.rs | 2 +- shared/src/core/image.rs | 1 - shared/src/core/medium.rs | 45 ++++++----- shared/src/core/sampler.rs | 4 +- shared/src/lights/distant.rs | 16 ++++ shared/src/lights/infinite.rs | 87 +++++++++++++++++++--- shared/src/lights/point.rs | 22 +++++- shared/src/lights/sampler.rs | 4 +- shared/src/lights/spot.rs | 28 ++++++- shared/src/utils/math.rs | 2 +- src/cameras/mod.rs | 3 - src/cameras/perspective.rs | 1 - src/cameras/realistic.rs | 100 ------------------------- src/cameras/spherical.rs | 1 - src/core/camera.rs | 12 ++- src/core/medium.rs | 28 +------ src/core/scene/scene.rs | 2 +- src/films/gbuffer.rs | 42 +---------- src/films/rgb.rs | 56 +------------- src/films/spectral.rs | 85 ++------------------- src/lib.rs | 1 - src/lights/distant.rs | 22 ------ src/lights/infinite.rs | 100 ------------------------- src/lights/mod.rs | 7 -- src/lights/point.rs | 30 +------- src/lights/sampler.rs | 31 ++++---- src/lights/spot.rs | 40 +--------- 29 files changed, 393 insertions(+), 574 deletions(-) delete mode 100644 src/cameras/mod.rs delete mode 100644 src/cameras/perspective.rs delete mode 100644 src/cameras/realistic.rs delete mode 100644 src/cameras/spherical.rs diff --git a/shared/src/cameras/realistic.rs b/shared/src/cameras/realistic.rs index 0f513da..523a302 100644 --- a/shared/src/cameras/realistic.rs +++ b/shared/src/cameras/realistic.rs @@ -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, + ) -> 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 = 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(); diff --git a/shared/src/core/film.rs b/shared/src/core/film.rs index 906ab66..f5ca9aa 100644 --- a/shared/src/core/film.rs +++ b/shared/src/core/film.rs @@ -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 = 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, pub output_rgbf_from_sensor_rgb: SquareMatrix, - pub bucket_sums: *mut f64, - pub weight_sums: *mut f64, - pub bucket_splats: *mut AtomicFloat, + pub bucket_sums: GVec, + pub weight_sums: GVec, + pub bucket_splats: GVec, } 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::::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 } diff --git a/shared/src/core/filter.rs b/shared/src/core/filter.rs index b783e6a..a794463 100644 --- a/shared/src/core/filter.rs +++ b/shared/src/core/filter.rs @@ -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 { diff --git a/shared/src/core/image.rs b/shared/src/core/image.rs index 2a29748..ea13e03 100644 --- a/shared/src/core/image.rs +++ b/shared/src/core/image.rs @@ -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; diff --git a/shared/src/core/medium.rs b/shared/src/core/medium.rs index a957c7c..233dce1 100644 --- a/shared/src/core/medium.rs +++ b/shared/src/core/medium.rs @@ -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, 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; } } diff --git a/shared/src/core/sampler.rs b/shared/src/core/sampler.rs index 760fb6d..cfb7320 100644 --- a/shared/src/core/sampler.rs +++ b/shared/src/core/sampler.rs @@ -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, + pub digit_permutations: GVec, } #[allow(clippy::derivable_impls)] diff --git a/shared/src/lights/distant.rs b/shared/src/lights/distant.rs index 017cca0..4cd3231 100644 --- a/shared/src/lights/distant.rs +++ b/shared/src/lights/distant.rs @@ -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, diff --git a/shared/src/lights/infinite.rs b/shared/src/lights/infinite.rs index c46f138..db93c96 100644 --- a/shared/src/lights/infinite.rs +++ b/shared/src/lights/infinite.rs @@ -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, + ) -> 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, pub image_color_space: Ptr, - pub distrib: Ptr, - pub compensated_distrib: Ptr, + pub distrib: Ptr, + pub compensated_distrib: Ptr, 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, + image_color_space: Ptr, + distrib: Ptr, + compensated_distrib: Ptr, + ) -> 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, + image_color_space: Ptr, + portal: [Point3f; 4], + portal_frame: Frame, + distribution: Ptr, + ) -> 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 { diff --git a/shared/src/lights/point.rs b/shared/src/lights/point.rs index 6aab4c2..6059335 100644 --- a/shared/src/lights/point.rs +++ b/shared/src/lights/point.rs @@ -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, } +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 diff --git a/shared/src/lights/sampler.rs b/shared/src/lights/sampler.rs index 2acc6d4..a8548d1 100644 --- a/shared/src/lights/sampler.rs +++ b/shared/src/lights/sampler.rs @@ -198,12 +198,12 @@ pub enum LightSampler { #[derive(Clone, Debug)] pub struct UniformLightSampler { - lights: *const Light, + lights: Ptr, lights_len: u32, } impl UniformLightSampler { - pub fn new(lights: *const Light, lights_len: u32) -> Self { + pub fn new(lights: Ptr, lights_len: u32) -> Self { Self { lights, lights_len } } diff --git a/shared/src/lights/spot.rs b/shared/src/lights/spot.rs index 3a86855..5857240 100644 --- a/shared/src/lights/spot.rs +++ b/shared/src/lights/spot.rs @@ -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( diff --git a/shared/src/utils/math.rs b/shared/src/utils/math.rs index 6401034..f222a90 100644 --- a/shared/src/utils/math.rs +++ b/shared/src/utils/math.rs @@ -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; diff --git a/src/cameras/mod.rs b/src/cameras/mod.rs deleted file mode 100644 index 1297d0a..0000000 --- a/src/cameras/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod perspective; -pub mod realistic; -pub mod spherical; diff --git a/src/cameras/perspective.rs b/src/cameras/perspective.rs deleted file mode 100644 index 8b13789..0000000 --- a/src/cameras/perspective.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/cameras/realistic.rs b/src/cameras/realistic.rs deleted file mode 100644 index d43f992..0000000 --- a/src/cameras/realistic.rs +++ /dev/null @@ -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, - element_interfaces: Vec, -} - -#[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, - ) -> 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 = 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 } - } -} diff --git a/src/cameras/spherical.rs b/src/cameras/spherical.rs deleted file mode 100644 index 8b13789..0000000 --- a/src/cameras/spherical.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/core/camera.rs b/src/core/camera.rs index 7263976..e2ecf19 100644 --- a/src/core/camera.rs +++ b/src/core/camera.rs @@ -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(); diff --git a/src/core/medium.rs b/src/core/medium.rs index e2bb5a6..4297436 100644 --- a/src/core/medium.rs +++ b/src/core/medium.rs @@ -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, -} - -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, 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 { diff --git a/src/core/scene/scene.rs b/src/core/scene/scene.rs index e7bd4c0..eb2c0b3 100644 --- a/src/core/scene/scene.rs +++ b/src/core/scene/scene.rs @@ -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}; diff --git a/src/films/gbuffer.rs b/src/films/gbuffer.rs index a3584d1..73ef227 100644 --- a/src/films/gbuffer.rs +++ b/src/films/gbuffer.rs @@ -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)) } } diff --git a/src/films/rgb.rs b/src/films/rgb.rs index cd39dd5..61e6e44 100644 --- a/src/films/rgb.rs +++ b/src/films/rgb.rs @@ -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, -} - -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 = 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)) } } diff --git a/src/films/spectral.rs b/src/films/spectral.rs index 80b8372..85fcd71 100644 --- a/src/films/spectral.rs +++ b/src/films/spectral.rs @@ -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, - bucket_sums: Vec, - weight_sums: Vec, - bucket_splats: Vec, -} - -pub struct SpectralFilmHost { - pub device: SpectralFilm, - storage: Arc, -} - -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::::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 { + // 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)) } } diff --git a/src/lib.rs b/src/lib.rs index 4b4627b..6ea9678 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,5 @@ #![feature(f16)] #[allow(dead_code)] -pub mod cameras; pub mod core; pub mod films; pub mod filters; diff --git a/src/lights/distant.rs b/src/lights/distant.rs index 9adddbb..fb18dd9 100644 --- a/src/lights/distant.rs +++ b/src/lights/distant.rs @@ -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, diff --git a/src/lights/infinite.rs b/src/lights/infinite.rs index 370d05f..b53ec15 100644 --- a/src/lights/infinite.rs +++ b/src/lights/infinite.rs @@ -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, - image_color_space: Ptr, - distrib: Ptr, - compensated_distrib: Ptr, - ) -> Self; -} - -impl CreateImageInfiniteLight for ImageInfiniteLight { - fn new( - render_from_light: Transform, - scale: Float, - image: Ptr, - image_color_space: Ptr, - distrib: Ptr, - compensated_distrib: Ptr, - ) -> 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, - image_color_space: Ptr, - portal: [Point3f; 4], - portal_frame: Frame, - distribution: Ptr, - ) -> Self; -} - -impl CreatePortalInfiniteLight for PortalInfiniteLight { - fn new( - render_from_light: Transform, - scale: Float, - image: Ptr, - image_color_space: Ptr, - portal: [Point3f; 4], - portal_frame: Frame, - distribution: Ptr, - ) -> 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) -> Self; -} - -impl CreateUniformInfiniteLight for UniformInfiniteLight { - fn new(render_from_light: Transform, scale: Float, lemit: Ptr) -> 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, diff --git a/src/lights/mod.rs b/src/lights/mod.rs index e347ad8..cbcaadc 100644 --- a/src/lights/mod.rs +++ b/src/lights/mod.rs @@ -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; diff --git a/src/lights/point.rs b/src/lights/point.rs index 8c8db4e..6e7793e 100644 --- a/src/lights/point.rs +++ b/src/lights/point.rs @@ -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, diff --git a/src/lights/sampler.rs b/src/lights/sampler.rs index 7d4159e..126d8a8 100644 --- a/src/lights/sampler.rs +++ b/src/lights/sampler.rs @@ -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>, pub light_to_index: HashMap, - 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 = 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 = 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, + // } + // } } diff --git a/src/lights/spot.rs b/src/lights/spot.rs index 95fae0d..7e1d3fa 100644 --- a/src/lights/spot.rs +++ b/src/lights/spot.rs @@ -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,