162 lines
3.7 KiB
Rust
162 lines
3.7 KiB
Rust
use super::{
|
|
DenselySampledSpectrum, RGBColorSpace, SampledSpectrum, SampledWavelengths, LAMBDA_MAX,
|
|
LAMBDA_MIN, N_SPECTRUM_SAMPLES,
|
|
};
|
|
use crate::core::color::{RGBSigmoidPolynomial, RGB, XYZ};
|
|
use crate::core::spectrum::SpectrumTrait;
|
|
use crate::utils::Ptr;
|
|
|
|
use crate::Float;
|
|
|
|
#[repr(C)]
|
|
#[derive(Debug, Clone, Copy)]
|
|
pub struct RGBAlbedoSpectrum {
|
|
pub rsp: RGBSigmoidPolynomial,
|
|
}
|
|
|
|
impl RGBAlbedoSpectrum {
|
|
pub fn new(cs: &RGBColorSpace, rgb: RGB) -> Self {
|
|
Self {
|
|
rsp: cs.to_rgb_coeffs(rgb),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpectrumTrait for RGBAlbedoSpectrum {
|
|
fn evaluate(&self, lambda: Float) -> Float {
|
|
self.rsp.evaluate(lambda)
|
|
}
|
|
|
|
fn max_value(&self) -> Float {
|
|
self.rsp.max_value()
|
|
}
|
|
}
|
|
|
|
#[repr(C)]
|
|
#[derive(Debug, Default, Clone, Copy)]
|
|
pub struct UnboundedRGBSpectrum {
|
|
pub scale: Float,
|
|
pub rsp: RGBSigmoidPolynomial,
|
|
}
|
|
|
|
impl UnboundedRGBSpectrum {
|
|
pub fn new(cs: RGBColorSpace, rgb: RGB) -> Self {
|
|
let m = rgb.r.max(rgb.g).max(rgb.b);
|
|
let scale = 2.0 * m;
|
|
let scaled_rgb = if scale != 0.0 {
|
|
rgb / scale
|
|
} else {
|
|
RGB::new(0.0, 0.0, 0.0)
|
|
};
|
|
Self {
|
|
scale,
|
|
rsp: cs.to_rgb_coeffs(scaled_rgb),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpectrumTrait for UnboundedRGBSpectrum {
|
|
fn evaluate(&self, lambda: Float) -> Float {
|
|
self.scale * self.rsp.evaluate(lambda)
|
|
}
|
|
|
|
fn max_value(&self) -> Float {
|
|
self.scale * self.rsp.max_value()
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, Default)]
|
|
pub struct RGBIlluminantSpectrum {
|
|
pub scale: Float,
|
|
pub rsp: RGBSigmoidPolynomial,
|
|
pub illuminant: Ptr<DenselySampledSpectrum>,
|
|
}
|
|
|
|
impl RGBIlluminantSpectrum {
|
|
pub fn new(cs: &RGBColorSpace, rgb: RGB) -> Self {
|
|
let illuminant = cs.illuminant;
|
|
let m = rgb.max_component_value();
|
|
let scale = 2. * m;
|
|
let rsp = cs.to_rgb_coeffs(if scale != 0. {
|
|
rgb / scale
|
|
} else {
|
|
RGB::new(0., 0., 0.)
|
|
});
|
|
Self {
|
|
scale,
|
|
rsp,
|
|
illuminant,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpectrumTrait for RGBIlluminantSpectrum {
|
|
fn evaluate(&self, lambda: Float) -> Float {
|
|
if self.illuminant.is_null() {
|
|
return 0.;
|
|
}
|
|
self.scale * self.rsp.evaluate(lambda) * self.illuminant.evaluate(lambda)
|
|
}
|
|
|
|
fn sample(&self, lambda: &SampledWavelengths) -> SampledSpectrum {
|
|
if self.illuminant.is_null() {
|
|
return SampledSpectrum::new(0.);
|
|
}
|
|
SampledSpectrum::from_fn(|i| self.scale * self.rsp.evaluate(lambda[i]))
|
|
}
|
|
|
|
fn max_value(&self) -> Float {
|
|
if self.illuminant.is_null() {
|
|
return 0.;
|
|
}
|
|
self.scale * self.rsp.max_value() * self.illuminant.max_value()
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
pub struct RGBSpectrum {
|
|
pub c: [Float; 3],
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
pub struct RGBUnboundedSpectrum {
|
|
pub scale: Float,
|
|
pub rsp: RGBSigmoidPolynomial,
|
|
}
|
|
|
|
impl Default for RGBUnboundedSpectrum {
|
|
fn default() -> Self {
|
|
Self {
|
|
scale: 0.0,
|
|
rsp: RGBSigmoidPolynomial::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RGBUnboundedSpectrum {
|
|
pub fn new(cs: &RGBColorSpace, rgb: RGB) -> Self {
|
|
let m = rgb.max_component_value();
|
|
|
|
let scale = 2.0 * m;
|
|
|
|
let rgb_norm = if scale > 0.0 {
|
|
rgb / scale
|
|
} else {
|
|
RGB::new(0.0, 0.0, 0.0)
|
|
};
|
|
|
|
let rsp = cs.to_rgb_coeffs(rgb_norm);
|
|
|
|
Self { scale, rsp }
|
|
}
|
|
}
|
|
|
|
impl SpectrumTrait for RGBUnboundedSpectrum {
|
|
fn evaluate(&self, lambda: Float) -> Float {
|
|
self.scale * self.rsp.evaluate(lambda)
|
|
}
|
|
|
|
fn max_value(&self) -> Float {
|
|
self.scale * self.rsp.max_value()
|
|
}
|
|
}
|