pbrt/src/core/light.rs

92 lines
3 KiB
Rust

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<DenselySampledSpectrum> {
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<Medium>,
parameters: &ParameterDictionary,
loc: &FileLoc,
camera_transform: CameraTransform,
arena: &Arena,
) -> Result<Light> {
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<Medium>,
parameters: &ParameterDictionary,
loc: &FileLoc,
shape: &Shape,
alpha_tex: &FloatTexture,
colorspace: Option<&RGBColorSpace>,
arena: &Arena,
) -> Result<Light> {
crate::lights::diffuse::create(
render_from_light, medium, parameters, loc,
shape, alpha_tex, colorspace, arena,
)
}