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 {
|
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) {
|
pub fn compute_cardinal_points(r_in: Ray, r_out: Ray) -> (Float, Float) {
|
||||||
let tf = -r_out.o.x() / r_out.d.x();
|
let tf = -r_out.o.x() / r_out.d.x();
|
||||||
let tp = (r_in.o.x() - 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::sampling::VarianceEstimator;
|
||||||
use crate::utils::transform::AnimatedTransform;
|
use crate::utils::transform::AnimatedTransform;
|
||||||
use crate::utils::{gpu_array_from_fn, AtomicFloat};
|
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;
|
use num_traits::Float as NumFloat;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
@ -50,6 +50,43 @@ impl Default for RGBPixel {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RGBFilm {
|
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 {
|
pub fn base(&self) -> &FilmBase {
|
||||||
&self.base
|
&self.base
|
||||||
}
|
}
|
||||||
|
|
@ -214,6 +251,37 @@ pub struct GBufferFilm {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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 {
|
pub fn base(&self) -> &FilmBase {
|
||||||
&self.base
|
&self.base
|
||||||
}
|
}
|
||||||
|
|
@ -351,24 +419,73 @@ impl Default for SpectralPixel {
|
||||||
#[cfg_attr(target_os = "cuda", derive(Copy, Clone))]
|
#[cfg_attr(target_os = "cuda", derive(Copy, Clone))]
|
||||||
pub struct SpectralFilm {
|
pub struct SpectralFilm {
|
||||||
pub base: FilmBase,
|
pub base: FilmBase,
|
||||||
pub colorspace: RGBColorSpace,
|
|
||||||
pub lambda_min: Float,
|
pub lambda_min: Float,
|
||||||
pub lambda_max: Float,
|
pub lambda_max: Float,
|
||||||
pub n_buckets: usize,
|
pub n_buckets: usize,
|
||||||
pub max_component_value: Float,
|
pub max_component_value: Float,
|
||||||
pub write_fp16: bool,
|
pub write_fp16: bool,
|
||||||
pub filter_integral: Float,
|
pub filter_integral: Float,
|
||||||
|
pub colorspace: RGBColorSpace,
|
||||||
pub pixels: Array2D<SpectralPixel>,
|
pub pixels: Array2D<SpectralPixel>,
|
||||||
pub output_rgbf_from_sensor_rgb: SquareMatrix<Float, 3>,
|
pub output_rgbf_from_sensor_rgb: SquareMatrix<Float, 3>,
|
||||||
pub bucket_sums: *mut f64,
|
pub bucket_sums: GVec<f64>,
|
||||||
pub weight_sums: *mut f64,
|
pub weight_sums: GVec<f64>,
|
||||||
pub bucket_splats: *mut AtomicFloat,
|
pub bucket_splats: GVec<AtomicFloat>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for SpectralFilm {}
|
unsafe impl Send for SpectralFilm {}
|
||||||
unsafe impl Sync for SpectralFilm {}
|
unsafe impl Sync for SpectralFilm {}
|
||||||
|
|
||||||
impl 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 {
|
pub fn base(&self) -> &FilmBase {
|
||||||
&self.base
|
&self.base
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use crate::core::geometry::{Bounds2f, Bounds2i, Point2f, Point2i, Vector2f};
|
||||||
use crate::filters::*;
|
use crate::filters::*;
|
||||||
use crate::utils::math::{gaussian, gaussian_integral, lerp, sample_tent, windowed_sinc};
|
use crate::utils::math::{gaussian, gaussian_integral, lerp, sample_tent, windowed_sinc};
|
||||||
use crate::utils::sampling::PiecewiseConstant2D;
|
use crate::utils::sampling::PiecewiseConstant2D;
|
||||||
use crate::{DeviceArray2D, Float};
|
use crate::{Array2D, Float};
|
||||||
use enum_dispatch::enum_dispatch;
|
use enum_dispatch::enum_dispatch;
|
||||||
|
|
||||||
pub struct FilterSample {
|
pub struct FilterSample {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::core::color::{ColorEncoding, ColorEncodingTrait, LINEAR};
|
use crate::core::color::{ColorEncoding, ColorEncodingTrait, LINEAR};
|
||||||
use crate::core::geometry::{Bounds2f, Point2f, Point2fi, Point2i};
|
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::utils::math::{f16_to_f32_software, lerp, square};
|
||||||
use crate::Float;
|
use crate::Float;
|
||||||
use crate::GVec;
|
use crate::GVec;
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,18 @@
|
||||||
use enum_dispatch::enum_dispatch;
|
|
||||||
|
|
||||||
use crate::core::geometry::{
|
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::pbrt::{Float, INV_4_PI, PI};
|
||||||
use crate::core::spectrum::{Spectrum, SpectrumTrait};
|
use crate::core::spectrum::{Spectrum, SpectrumTrait};
|
||||||
use crate::spectra::{
|
use crate::spectra::{
|
||||||
BlackbodySpectrum, DenselySampledSpectrum, LAMBDA_MAX, LAMBDA_MIN, RGBIlluminantSpectrum,
|
BlackbodySpectrum, DenselySampledSpectrum, RGBIlluminantSpectrum, RGBUnboundedSpectrum,
|
||||||
RGBUnboundedSpectrum, SampledSpectrum, SampledWavelengths,
|
SampledSpectrum, SampledWavelengths, LAMBDA_MAX, LAMBDA_MIN,
|
||||||
};
|
};
|
||||||
use crate::utils::containers::SampledGrid;
|
use crate::utils::containers::SampledGrid;
|
||||||
use crate::utils::math::{clamp, square};
|
use crate::utils::math::{clamp, square};
|
||||||
use crate::utils::ptr::Ptr;
|
|
||||||
use crate::utils::rng::Rng;
|
use crate::utils::rng::Rng;
|
||||||
use crate::utils::transform::Transform;
|
use crate::utils::transform::Transform;
|
||||||
|
use crate::{gvec_with_capacity, GVec, Ptr};
|
||||||
|
use enum_dispatch::enum_dispatch;
|
||||||
use num_traits::Float as NumFloat;
|
use num_traits::Float as NumFloat;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
@ -90,11 +89,11 @@ impl PhaseFunctionTrait for HGPhaseFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct MajorantGrid {
|
pub struct MajorantGrid {
|
||||||
pub bounds: Bounds3f,
|
pub bounds: Bounds3f,
|
||||||
pub res: Point3i,
|
pub res: Point3i,
|
||||||
pub voxels: *mut Float,
|
pub voxels: GVec<Float>,
|
||||||
pub n_voxels: u32,
|
pub n_voxels: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -102,21 +101,21 @@ unsafe impl Send for MajorantGrid {}
|
||||||
unsafe impl Sync for MajorantGrid {}
|
unsafe impl Sync for MajorantGrid {}
|
||||||
|
|
||||||
impl MajorantGrid {
|
impl MajorantGrid {
|
||||||
// #[cfg(not(target_os = "cuda"))]
|
#[cfg(not(target_os = "cuda"))]
|
||||||
// pub fn new(bounds: Bounds3f, res: Point3i) -> Self {
|
pub fn new(bounds: Bounds3f, res: Point3i) -> Self {
|
||||||
// let n_voxels = (res.x() * res.y() * res.z()) as usize;
|
let n_voxels = (res.x() * res.y() * res.z()) as usize;
|
||||||
// let voxels = Vec::with_capacity(n_voxels);
|
let voxels = gvec_with_capacity(n_voxels);
|
||||||
// Self {
|
Self {
|
||||||
// bounds,
|
bounds,
|
||||||
// res,
|
res,
|
||||||
// voxels: voxels.as_ptr(),
|
voxels,
|
||||||
// n_voxels: n_voxels as u32,
|
n_voxels: n_voxels as u32,
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn is_valid(&self) -> bool {
|
fn is_valid(&self) -> bool {
|
||||||
!self.voxels.is_null()
|
!self.voxels.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
|
@ -128,7 +127,7 @@ impl MajorantGrid {
|
||||||
let idx = z * self.res.x() * self.res.y() + y * self.res.x() + x;
|
let idx = z * self.res.x() * self.res.y() + y * self.res.x() + x;
|
||||||
|
|
||||||
if idx >= 0 && (idx as u32) < self.n_voxels {
|
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 {
|
} else {
|
||||||
0.0
|
0.0
|
||||||
}
|
}
|
||||||
|
|
@ -143,7 +142,7 @@ impl MajorantGrid {
|
||||||
let idx = x + self.res.x() * (y + self.res.y() * z);
|
let idx = x + self.res.x() * (y + self.res.y() * z);
|
||||||
|
|
||||||
unsafe {
|
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,
|
clamp, encode_morton_2, inverse_radical_inverse, lerp, log2_int,
|
||||||
owen_scrambled_radical_inverse, permutation_element, radical_inverse, round_up_pow2,
|
owen_scrambled_radical_inverse, permutation_element, radical_inverse, round_up_pow2,
|
||||||
scrambled_radical_inverse, sobol_interval_to_index, sobol_sample, BinaryPermuteScrambler,
|
scrambled_radical_inverse, sobol_interval_to_index, sobol_sample, BinaryPermuteScrambler,
|
||||||
DeviceDigitPermutation, FastOwenScrambler, NoRandomizer, OwenScrambler, Scrambler,
|
DigitPermutation, FastOwenScrambler, NoRandomizer, OwenScrambler, Scrambler,
|
||||||
PRIME_TABLE_SIZE,
|
PRIME_TABLE_SIZE,
|
||||||
};
|
};
|
||||||
use crate::utils::rng::Rng;
|
use crate::utils::rng::Rng;
|
||||||
|
|
@ -100,7 +100,7 @@ pub struct HaltonSampler {
|
||||||
pub mult_inverse: [u64; 2],
|
pub mult_inverse: [u64; 2],
|
||||||
pub halton_index: u64,
|
pub halton_index: u64,
|
||||||
pub dim: u32,
|
pub dim: u32,
|
||||||
pub digit_permutations: GVec<DeviceDigitPermutation>,
|
pub digit_permutations: GVec<DigitPermutation>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::derivable_impls)]
|
#[allow(clippy::derivable_impls)]
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,22 @@ pub struct DistantLight {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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(
|
pub fn sample_li_base(
|
||||||
&self,
|
&self,
|
||||||
ctx_p: Point3f,
|
ctx_p: Point3f,
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@ use crate::spectra::{DenselySampledSpectrum, SampledSpectrum, SampledWavelengths
|
||||||
use crate::spectra::{RGBColorSpace, RGBIlluminantSpectrum};
|
use crate::spectra::{RGBColorSpace, RGBIlluminantSpectrum};
|
||||||
use crate::utils::math::{clamp, equal_area_sphere_to_square, equal_area_square_to_sphere, square};
|
use crate::utils::math::{clamp, equal_area_sphere_to_square, equal_area_square_to_sphere, square};
|
||||||
use crate::utils::sampling::{
|
use crate::utils::sampling::{
|
||||||
AliasTable, DevicePiecewiseConstant2D, WindowedPiecewiseConstant2D,
|
sample_uniform_sphere, uniform_sphere_pdf, AliasTable, DevicePiecewiseConstant2D,
|
||||||
sample_uniform_sphere, uniform_sphere_pdf,
|
WindowedPiecewiseConstant2D,
|
||||||
};
|
};
|
||||||
use crate::utils::{Ptr, Transform};
|
use crate::utils::{Ptr, Transform};
|
||||||
use crate::{Float, PI};
|
use crate::{Float, PI};
|
||||||
|
|
@ -35,6 +35,27 @@ pub struct UniformInfiniteLight {
|
||||||
unsafe impl Send for UniformInfiniteLight {}
|
unsafe impl Send for UniformInfiniteLight {}
|
||||||
unsafe impl Sync 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 {
|
impl LightTrait for UniformInfiniteLight {
|
||||||
fn base(&self) -> &LightBase {
|
fn base(&self) -> &LightBase {
|
||||||
&self.base
|
&self.base
|
||||||
|
|
@ -116,8 +137,8 @@ pub struct ImageInfiniteLight {
|
||||||
pub base: LightBase,
|
pub base: LightBase,
|
||||||
pub image: Ptr<Image>,
|
pub image: Ptr<Image>,
|
||||||
pub image_color_space: Ptr<RGBColorSpace>,
|
pub image_color_space: Ptr<RGBColorSpace>,
|
||||||
pub distrib: Ptr<DevicePiecewiseConstant2D>,
|
pub distrib: Ptr<PiecewiseConstant2D>,
|
||||||
pub compensated_distrib: Ptr<DevicePiecewiseConstant2D>,
|
pub compensated_distrib: Ptr<PiecewiseConstant2D>,
|
||||||
pub scale: Float,
|
pub scale: Float,
|
||||||
pub scene_radius: Float,
|
pub scene_radius: Float,
|
||||||
pub scene_center: Point3f,
|
pub scene_center: Point3f,
|
||||||
|
|
@ -127,14 +148,35 @@ unsafe impl Send for ImageInfiniteLight {}
|
||||||
unsafe impl Sync for ImageInfiniteLight {}
|
unsafe impl Sync for ImageInfiniteLight {}
|
||||||
|
|
||||||
impl 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 {
|
fn image_le(&self, uv: Point2f, lambda: &SampledWavelengths) -> SampledSpectrum {
|
||||||
let mut rgb = RGB::default();
|
let mut rgb = RGB::default();
|
||||||
for c in 0..3 {
|
for c in 0..3 {
|
||||||
rgb[c] = self.image.lookup_nearest_channel_with_wrap(
|
rgb[c] = self.image.get_ch(uv, c, WrapMode::OctahedralSphere.into());
|
||||||
uv,
|
|
||||||
c,
|
|
||||||
WrapMode::OctahedralSphere.into(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
let spec = RGBIlluminantSpectrum::new(&self.image_color_space, rgb.clamp_zero());
|
let spec = RGBIlluminantSpectrum::new(&self.image_color_space, rgb.clamp_zero());
|
||||||
self.scale * spec.sample(lambda)
|
self.scale * spec.sample(lambda)
|
||||||
|
|
@ -261,6 +303,33 @@ pub struct PortalInfiniteLight {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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 {
|
pub fn image_lookup(&self, uv: Point2f, lambda: &SampledWavelengths) -> SampledSpectrum {
|
||||||
let mut rgb = RGB::default();
|
let mut rgb = RGB::default();
|
||||||
for c in 0..3 {
|
for c in 0..3 {
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,7 @@ use crate::core::light::{
|
||||||
};
|
};
|
||||||
use crate::core::spectrum::SpectrumTrait;
|
use crate::core::spectrum::SpectrumTrait;
|
||||||
use crate::spectra::{DenselySampledSpectrum, SampledSpectrum, SampledWavelengths};
|
use crate::spectra::{DenselySampledSpectrum, SampledSpectrum, SampledWavelengths};
|
||||||
use crate::utils::Ptr;
|
use crate::{Float, PI, Ptr, Transform};
|
||||||
use crate::{Float, PI};
|
|
||||||
use num_traits::Float as NumFloat;
|
use num_traits::Float as NumFloat;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
@ -19,6 +18,25 @@ pub struct PointLight {
|
||||||
pub i: Ptr<DenselySampledSpectrum>,
|
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 {
|
impl LightTrait for PointLight {
|
||||||
fn base(&self) -> &LightBase {
|
fn base(&self) -> &LightBase {
|
||||||
&self.base
|
&self.base
|
||||||
|
|
|
||||||
|
|
@ -198,12 +198,12 @@ pub enum LightSampler {
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct UniformLightSampler {
|
pub struct UniformLightSampler {
|
||||||
lights: *const Light,
|
lights: Ptr<Light>,
|
||||||
lights_len: u32,
|
lights_len: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UniformLightSampler {
|
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 }
|
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::light::{LightBase, LightBounds, LightLiSample, LightSampleContext, LightTrait};
|
||||||
use crate::core::spectrum::SpectrumTrait;
|
use crate::core::spectrum::SpectrumTrait;
|
||||||
use crate::spectra::{DenselySampledSpectrum, SampledSpectrum, SampledWavelengths};
|
use crate::spectra::{DenselySampledSpectrum, SampledSpectrum, SampledWavelengths};
|
||||||
use crate::utils::Ptr;
|
use crate::{Float, PI, Ptr, Transform};
|
||||||
use crate::{Float, PI};
|
|
||||||
use num_traits::Float as NumFloat;
|
use num_traits::Float as NumFloat;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
@ -20,6 +19,31 @@ pub struct SpotLight {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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 {
|
pub fn i(&self, w: Vector3f, lambda: &SampledWavelengths) -> SampledSpectrum {
|
||||||
let cos_theta = w.z(); // assuming normalized in light space
|
let cos_theta = w.z(); // assuming normalized in light space
|
||||||
let falloff = crate::utils::math::smooth_step(
|
let falloff = crate::utils::math::smooth_step(
|
||||||
|
|
|
||||||
|
|
@ -821,7 +821,7 @@ impl DigitPermutation {
|
||||||
pub fn scrambled_radical_inverse(
|
pub fn scrambled_radical_inverse(
|
||||||
base_index: u32,
|
base_index: u32,
|
||||||
mut a: u64,
|
mut a: u64,
|
||||||
perm: &DeviceDigitPermutation,
|
perm: &DigitPermutation,
|
||||||
) -> Float {
|
) -> Float {
|
||||||
let base = PRIMES[base_index as usize] as u64;
|
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::ImageMetadata;
|
||||||
use crate::core::image::{Image, ImageIO};
|
use crate::core::image::{Image, ImageIO};
|
||||||
use crate::globals::get_options;
|
use crate::globals::get_options;
|
||||||
use crate::utils::read_float_file;
|
use crate::utils::read_float_file;
|
||||||
use crate::utils::{Arena, FileLoc, ParameterDictionary};
|
use crate::{Arena, FileLoc, ParameterDictionary};
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use shared::cameras::*;
|
use shared::cameras::*;
|
||||||
use shared::core::camera::{Camera, CameraBase, CameraTrait, CameraTransform};
|
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::image::PixelFormat;
|
||||||
use shared::core::medium::Medium;
|
use shared::core::medium::Medium;
|
||||||
use shared::utils::math::square;
|
use shared::utils::math::square;
|
||||||
use shared::Ptr;
|
use shared::{Float, Ptr, PI};
|
||||||
use shared::{Float, PI};
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
|
@ -380,16 +378,16 @@ impl CameraFactory for Camera {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let camera = RealisticCameraHost::new(
|
let camera = RealisticCamera::new(
|
||||||
base,
|
base,
|
||||||
&lens_params,
|
&lens_params,
|
||||||
focal_distance,
|
focal_distance,
|
||||||
aperture_diameter,
|
aperture_diameter,
|
||||||
Arc::from(aperture_image.unwrap()),
|
Ptr::from(&*aperture_image.unwrap()),
|
||||||
);
|
);
|
||||||
|
|
||||||
arena.alloc(camera);
|
arena.alloc(camera);
|
||||||
Ok(Camera::Realistic(camera.device()))
|
Ok(Camera::Realistic(camera))
|
||||||
}
|
}
|
||||||
"spherical" => {
|
"spherical" => {
|
||||||
let _full_res = film.full_resolution();
|
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::medium::{GridMedium, HGPhaseFunction, HomogeneousMedium, RGBGridMedium};
|
||||||
use shared::core::spectrum::{Spectrum, SpectrumTrait};
|
use shared::core::spectrum::{Spectrum, SpectrumTrait};
|
||||||
use shared::spectra::{RGBIlluminantSpectrum, RGBUnboundedSpectrum, DenselySampledSpectrum};
|
use shared::spectra::{RGBIlluminantSpectrum, RGBUnboundedSpectrum, DenselySampledSpectrum};
|
||||||
use shared::utils::Transform;
|
|
||||||
use shared::utils::containers::SampledGrid;
|
use shared::utils::containers::SampledGrid;
|
||||||
use shared::{Float, core::medium::MajorantGrid};
|
use shared::{Float, Transform, 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 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait RGBGridMediumCreator {
|
pub trait RGBGridMediumCreator {
|
||||||
fn new(
|
fn new(
|
||||||
|
|
@ -52,7 +30,7 @@ impl RGBGridMediumCreator for RGBGridMedium {
|
||||||
le_grid: SampledGrid<RGBIlluminantSpectrum>,
|
le_grid: SampledGrid<RGBIlluminantSpectrum>,
|
||||||
le_scale: Float,
|
le_scale: Float,
|
||||||
) -> Self {
|
) -> 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 z in 0..majorant_grid.res.x() {
|
||||||
for y in 0..majorant_grid.res.y() {
|
for y in 0..majorant_grid.res.y() {
|
||||||
for x in 0..majorant_grid.res.x() {
|
for x in 0..majorant_grid.res.x() {
|
||||||
|
|
@ -116,7 +94,7 @@ impl GridMediumCreator for GridMedium {
|
||||||
|
|
||||||
let le_spec = DenselySampledSpectrum::from_spectrum(le);
|
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() {
|
let is_emissive = if temperature_grid.is_some() {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ use crate::core::texture::{FloatTexture, SpectrumTexture};
|
||||||
use crate::utils::parallel::{run_async, AsyncJob};
|
use crate::utils::parallel::{run_async, AsyncJob};
|
||||||
use crate::utils::parameters::{NamedTextures, ParameterDictionary, TextureParameterDictionary};
|
use crate::utils::parameters::{NamedTextures, ParameterDictionary, TextureParameterDictionary};
|
||||||
use crate::utils::resolve_filename;
|
use crate::utils::resolve_filename;
|
||||||
use crate::{Arena, DeviceRepr, FileLoc};
|
use crate::{Arena, FileLoc};
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use shared::core::camera::{Camera, CameraTransform};
|
use shared::core::camera::{Camera, CameraTransform};
|
||||||
|
|
|
||||||
|
|
@ -8,44 +8,6 @@ use shared::spectra::RGBColorSpace;
|
||||||
use shared::utils::AnimatedTransform;
|
use shared::utils::AnimatedTransform;
|
||||||
use std::path::Path;
|
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 {
|
impl CreateFilm for GBufferFilm {
|
||||||
fn create(
|
fn create(
|
||||||
|
|
@ -85,7 +47,7 @@ impl CreateFilm for GBufferFilm {
|
||||||
.into());
|
.into());
|
||||||
};
|
};
|
||||||
|
|
||||||
let film = GBufferFilmHost::new(
|
let film = GBufferFilm::new(
|
||||||
&film_base,
|
&film_base,
|
||||||
&output_from_render,
|
&output_from_render,
|
||||||
apply_inverse,
|
apply_inverse,
|
||||||
|
|
@ -94,6 +56,6 @@ impl CreateFilm for GBufferFilm {
|
||||||
write_fp16,
|
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::core::filter::FilterTrait;
|
||||||
use shared::spectra::RGBColorSpace;
|
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 {
|
impl CreateFilm for RGBFilm {
|
||||||
fn create(
|
fn create(
|
||||||
params: &ParameterDictionary,
|
params: &ParameterDictionary,
|
||||||
|
|
@ -74,7 +22,7 @@ impl CreateFilm for RGBFilm {
|
||||||
let write_fp16 = params.get_one_bool("savefp16", true)?;
|
let write_fp16 = params.get_one_bool("savefp16", true)?;
|
||||||
let sensor = PixelSensor::create(params, colorspace.clone(), exposure_time, loc)?;
|
let sensor = PixelSensor::create(params, colorspace.clone(), exposure_time, loc)?;
|
||||||
let film_base = FilmBase::create(params, filter, Some(&sensor.device()), loc)?;
|
let film_base = FilmBase::create(params, filter, Some(&sensor.device()), loc)?;
|
||||||
let film = RGBFilmHost::new(film_base, &colorspace, max_component_value, write_fp16);
|
let film = RGBFilm::new(film_base, &colorspace, max_component_value, write_fp16);
|
||||||
Ok(Film::RGB(film.device))
|
Ok(Film::RGB(film))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,91 +1,15 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::core::film::{CreateFilmBase, PixelSensor};
|
use crate::core::film::{CreateFilmBase, PixelSensor};
|
||||||
use crate::utils::containers::Array2D;
|
|
||||||
use crate::{Arena, FileLoc, ParameterDictionary};
|
use crate::{Arena, FileLoc, ParameterDictionary};
|
||||||
use anyhow::{Result, anyhow};
|
use anyhow::{Result, anyhow};
|
||||||
use shared::Float;
|
use shared::Float;
|
||||||
use shared::core::camera::CameraTransform;
|
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::core::filter::FilterTrait;
|
||||||
use shared::spectra::{LAMBDA_MAX, LAMBDA_MIN, RGBColorSpace};
|
use shared::spectra::{LAMBDA_MAX, LAMBDA_MIN};
|
||||||
use shared::utils::AtomicFloat;
|
|
||||||
use shared::utils::containers::Array2D;
|
|
||||||
use shared::utils::math::SquareMatrix;
|
use shared::utils::math::SquareMatrix;
|
||||||
use std::path::Path;
|
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 {
|
impl CreateFilm for SpectralFilm {
|
||||||
fn create(
|
fn create(
|
||||||
|
|
@ -96,6 +20,7 @@ impl CreateFilm for SpectralFilm {
|
||||||
loc: &FileLoc,
|
loc: &FileLoc,
|
||||||
_arena: &Arena,
|
_arena: &Arena,
|
||||||
) -> Result<Film> {
|
) -> Result<Film> {
|
||||||
|
// Missing default illuminant, use srgb
|
||||||
let colorspace = params.color_space.as_ref().unwrap();
|
let colorspace = params.color_space.as_ref().unwrap();
|
||||||
let max_component_value = params.get_one_float("maxcomponentvalue", Float::INFINITY)?;
|
let max_component_value = params.get_one_float("maxcomponentvalue", Float::INFINITY)?;
|
||||||
let write_fp16 = params.get_one_bool("savefp16", true)?;
|
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,
|
&film_base,
|
||||||
lambda_min,
|
lambda_min,
|
||||||
lambda_max,
|
lambda_max,
|
||||||
|
|
@ -127,6 +52,6 @@ impl CreateFilm for SpectralFilm {
|
||||||
write_fp16,
|
write_fp16,
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(Film::Spectral(film.device))
|
Ok(Film::Spectral(film))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
#![feature(f16)]
|
#![feature(f16)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub mod cameras;
|
|
||||||
pub mod core;
|
pub mod core;
|
||||||
pub mod films;
|
pub mod films;
|
||||||
pub mod filters;
|
pub mod filters;
|
||||||
|
|
|
||||||
|
|
@ -14,28 +14,6 @@ use shared::lights::DistantLight;
|
||||||
use shared::spectra::RGBColorSpace;
|
use shared::spectra::RGBColorSpace;
|
||||||
use shared::utils::{Ptr, Transform};
|
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(
|
pub fn create(
|
||||||
render_from_light: Transform,
|
render_from_light: Transform,
|
||||||
_medium: Option<Medium>,
|
_medium: Option<Medium>,
|
||||||
|
|
|
||||||
|
|
@ -21,106 +21,6 @@ use shared::utils::sampling::{PiecewiseConstant2D, WindowedPiecewiseConstant2D};
|
||||||
use shared::{Float, Ptr, Transform, PI};
|
use shared::{Float, Ptr, Transform, PI};
|
||||||
use std::path::Path;
|
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(
|
pub fn create(
|
||||||
render_from_light: Transform,
|
render_from_light: Transform,
|
||||||
_medium: Option<Medium>,
|
_medium: Option<Medium>,
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,3 @@ pub mod point;
|
||||||
pub mod projection;
|
pub mod projection;
|
||||||
pub mod sampler;
|
pub mod sampler;
|
||||||
pub mod spot;
|
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::core::texture::SpectrumType;
|
||||||
use shared::lights::PointLight;
|
use shared::lights::PointLight;
|
||||||
use shared::spectra::RGBColorSpace;
|
use shared::spectra::RGBColorSpace;
|
||||||
use shared::utils::{Ptr, Transform};
|
use shared::{Float, PI, Ptr, Transform};
|
||||||
use shared::{Float, PI};
|
|
||||||
|
|
||||||
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(
|
pub fn create(
|
||||||
render_from_light: Transform,
|
render_from_light: Transform,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::utils::sampling::AliasTableHost;
|
|
||||||
use crate::Arena;
|
use crate::Arena;
|
||||||
use shared::core::light::{Light, LightTrait};
|
use shared::core::light::{Light, LightTrait};
|
||||||
use shared::lights::sampler::PowerLightSampler;
|
use shared::lights::sampler::PowerLightSampler;
|
||||||
|
use shared::utils::sampling::AliasTable;
|
||||||
use shared::spectra::{SampledSpectrum, SampledWavelengths};
|
use shared::spectra::{SampledSpectrum, SampledWavelengths};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
@ -9,7 +9,7 @@ use std::sync::Arc;
|
||||||
pub struct PowerSamplerHost {
|
pub struct PowerSamplerHost {
|
||||||
pub lights: Vec<Arc<Light>>,
|
pub lights: Vec<Arc<Light>>,
|
||||||
pub light_to_index: HashMap<usize, usize>,
|
pub light_to_index: HashMap<usize, usize>,
|
||||||
pub alias_table: AliasTableHost,
|
pub alias_table: AliasTable,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PowerSamplerHost {
|
impl PowerSamplerHost {
|
||||||
|
|
@ -18,7 +18,7 @@ impl PowerSamplerHost {
|
||||||
return Self {
|
return Self {
|
||||||
lights: Vec::new(),
|
lights: Vec::new(),
|
||||||
light_to_index: HashMap::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());
|
light_power.push(phi.average());
|
||||||
}
|
}
|
||||||
|
|
||||||
let alias_table = AliasTableHost::new(&light_power);
|
let alias_table = AliasTable::new(&light_power);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
lights: lights_vec,
|
lights: lights_vec,
|
||||||
|
|
@ -46,16 +46,15 @@ impl PowerSamplerHost {
|
||||||
alias_table,
|
alias_table,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// pub fn to_device(&self, arena: &Arena) -> PowerLightSampler {
|
||||||
pub fn to_device(&self, arena: &Arena) -> PowerLightSampler {
|
// let device_lights: Vec<Light> = self.lights.iter().map(|l| (**l).clone()).collect();
|
||||||
let device_lights: Vec<Light> = self.lights.iter().map(|l| (**l).clone()).collect();
|
// let (lights_ptr, _) = arena.alloc_slice(&device_lights);
|
||||||
let (lights_ptr, _) = arena.alloc_slice(&device_lights);
|
// let alias_device = self.alias_table.to_device(arena);
|
||||||
let alias_device = self.alias_table.to_device(arena);
|
//
|
||||||
|
// PowerLightSampler {
|
||||||
PowerLightSampler {
|
// lights: lights_ptr,
|
||||||
lights: lights_ptr,
|
// lights_len: self.lights.len() as u32,
|
||||||
lights_len: self.lights.len() as u32,
|
// alias_table: alias_device,
|
||||||
alias_table: alias_device,
|
// }
|
||||||
}
|
// }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,45 +13,7 @@ use shared::lights::SpotLight;
|
||||||
use shared::spectra::RGBColorSpace;
|
use shared::spectra::RGBColorSpace;
|
||||||
use shared::utils::math::radians;
|
use shared::utils::math::radians;
|
||||||
use shared::utils::{Ptr, Transform};
|
use shared::utils::{Ptr, Transform};
|
||||||
use shared::{Float, PI};
|
use shared::{Float, PI, Ptr, Transform};
|
||||||
|
|
||||||
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(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create(
|
pub fn create(
|
||||||
render_from_light: Transform,
|
render_from_light: Transform,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue