use crate::core::spectrum::SPECTRUM_CACHE; use crate::core::texture::FloatTexture; use crate::{Arena, FileLoc, ParameterDictionary}; use anyhow::{anyhow, Result}; use shared::core::camera::CameraTransform; use shared::core::light::Light; use shared::core::medium::Medium; use shared::core::shape::Shape; use shared::core::spectrum::Spectrum; use shared::spectra::{DenselySampledSpectrum, RGBColorSpace}; use shared::Transform; use std::sync::Arc; pub fn lookup_spectrum(s: &Spectrum) -> Arc { let cache = &SPECTRUM_CACHE; let dense_spectrum = DenselySampledSpectrum::from_spectrum(s); cache.lookup(dense_spectrum) } fn dummy_shape() -> Shape { Shape::default() } fn dummy_alpha() -> FloatTexture { FloatTexture::default() } /// Create a non-area light. Returns a Light value — the caller decides /// whether to wrap it in Arc (host ownership) or arena.alloc (GPU). pub fn create_light( name: &str, render_from_light: Transform, medium: Option, parameters: &ParameterDictionary, loc: &FileLoc, camera_transform: CameraTransform, arena: &Arena, ) -> Result { let shape = dummy_shape(); let alpha = dummy_alpha(); match name { "point" => crate::lights::point::create( render_from_light, medium, parameters, loc, &shape, &alpha, None, arena, ), "spot" => crate::lights::spot::create( render_from_light, medium, parameters, loc, &shape, &alpha, None, arena, ), "distant" => crate::lights::distant::create( render_from_light, medium, parameters, loc, &shape, &alpha, None, arena, ), "goniometric" => crate::lights::goniometric::create( render_from_light, medium, parameters, loc, &shape, &alpha, None, arena, ), "projection" => crate::lights::projection::create( render_from_light, medium, parameters, loc, &shape, &alpha, None, arena, ), "infinite" => crate::lights::infinite::create( render_from_light, medium, camera_transform, parameters, None, loc, arena, ), "diffuse" => Err(anyhow!( "{}: \"diffuse\" is an area light; use create_area_light with a shape", loc )), _ => Err(anyhow!("{}: unknown light type \"{}\"", loc, name)), } } /// Create a diffuse area light bound to a specific shape. /// Returns a Light value. The individual light constructor still uses /// the arena internally for sub-allocations (shape, image, spectra), /// but the Light itself is returned as a value for the caller to place. pub fn create_area_light( render_from_light: Transform, medium: Option, parameters: &ParameterDictionary, loc: &FileLoc, shape: &Shape, alpha_tex: &FloatTexture, colorspace: Option<&RGBColorSpace>, arena: &Arena, ) -> Result { crate::lights::diffuse::create( render_from_light, medium, parameters, loc, shape, alpha_tex, colorspace, arena, ) }