96 lines
2.6 KiB
Rust
96 lines
2.6 KiB
Rust
pub mod cie;
|
|
pub mod color;
|
|
pub mod colorspace;
|
|
pub mod data;
|
|
pub mod rgb;
|
|
pub mod sampled;
|
|
pub mod simple;
|
|
|
|
use crate::core::pbrt::Float;
|
|
use crate::utils::file::read_float_file;
|
|
use enum_dispatch::enum_dispatch;
|
|
|
|
pub use color::{RGB, XYZ};
|
|
pub use colorspace::RGBColorSpace;
|
|
pub use data::*;
|
|
pub use rgb::*;
|
|
pub use sampled::{CIE_Y_INTEGRAL, LAMBDA_MAX, LAMBDA_MIN};
|
|
pub use sampled::{N_SPECTRUM_SAMPLES, SampledSpectrum, SampledWavelengths};
|
|
pub use simple::*;
|
|
//
|
|
#[enum_dispatch]
|
|
pub trait SpectrumProvider: Copy {
|
|
fn evaluate(&self, lambda: Float) -> Float;
|
|
fn max_value(&self) -> Float;
|
|
}
|
|
|
|
#[cfg(not(target_arch = "spirv"))]
|
|
impl SpectrumProvider for std::sync::Arc<DenselySampledSpectrum> {
|
|
fn evaluate(&self, lambda: Float) -> Float {
|
|
(**self).evaluate(lambda)
|
|
}
|
|
fn max_value(&self) -> Float {
|
|
(**self).max_value()
|
|
}
|
|
}
|
|
|
|
#[cfg(target_arch = "spirv")] // or target_os = "cuda"
|
|
impl SpectrumProvider for u32 {
|
|
fn evaluate(&self, lambda: Float) -> Float {
|
|
// Here you would call a global function that accesses
|
|
// a static buffer of spectra data
|
|
crate::gpu::lookup_global_spectrum(*self, lambda)
|
|
}
|
|
fn max_value(&self) -> Float {
|
|
crate::gpu::lookup_global_spectrum_max(*self)
|
|
}
|
|
}
|
|
|
|
#[enum_dispatch(SpectrumTrait)]
|
|
#[derive(Debug, Clone)]
|
|
pub enum Spectrum {
|
|
Constant(ConstantSpectrum),
|
|
DenselySampled(DenselySampledSpectrum),
|
|
PiecewiseLinear(PiecewiseLinearSpectrum),
|
|
Blackbody(BlackbodySpectrum),
|
|
RGBAlbedo(RGBAlbedoSpectrum),
|
|
RGBIlluminant(RGBIlluminantSpectrum),
|
|
RGBUnbounded(RGBUnboundedSpectrum),
|
|
}
|
|
|
|
impl Spectrum {
|
|
pub fn std_illuminant_d65() -> Self {
|
|
todo!()
|
|
}
|
|
|
|
pub fn to_xyz(&self) -> XYZ {
|
|
let x = self.inner_product(data::cie_x());
|
|
let y = self.inner_product(data::cie_y());
|
|
let z = self.inner_product(data::cie_z());
|
|
|
|
XYZ::new(x, y, z) / CIE_Y_INTEGRAL
|
|
}
|
|
|
|
fn to_rgb(&self, cs: &RGBColorSpace) -> RGB {
|
|
let xyz = self.to_xyz();
|
|
cs.to_rgb(xyz)
|
|
}
|
|
|
|
pub fn sample(&self, wavelengths: &SampledWavelengths) -> SampledSpectrum {
|
|
SampledSpectrum::from_fn(|i| self.evaluate(wavelengths[i]))
|
|
}
|
|
|
|
pub fn inner_product(&self, other: &Spectrum) -> Float {
|
|
let mut integral = 0.0;
|
|
// Iterate integer wavelengths.
|
|
for lambda in LAMBDA_MIN..=LAMBDA_MAX {
|
|
let l = lambda as Float;
|
|
integral += self.evaluate(l) * other.evaluate(l);
|
|
}
|
|
integral
|
|
}
|
|
|
|
pub fn is_constant(&self) -> bool {
|
|
matches!(self, Spectrum::Constant(_))
|
|
}
|
|
}
|