use crate::core::texture::{CreateSpectrumTexture, FloatTexture, SpectrumTexture}; use crate::core::texture::{FloatTextureTrait, SpectrumTextureTrait}; use crate::utils::{FileLoc, TextureParameterDictionary}; use crate::Arena; use anyhow::Result; use shared::core::spectrum::Spectrum; use shared::core::texture::{SpectrumType, TextureEvalContext}; use shared::spectra::{SampledSpectrum, SampledWavelengths, ConstantSpectrum}; use shared::utils::Transform; use shared::Float; use std::sync::Arc; #[derive(Clone, Debug)] pub struct FloatScaledTexture { pub tex: Arc, pub scale: Arc, } impl FloatScaledTexture { pub fn new(tex: Arc, scale: Arc) -> Self { Self { tex, scale } } pub fn create( _render_from_texture: &Transform, params: &TextureParameterDictionary, _loc: &FileLoc, _arena: &Arena, ) -> Result { let mut tex = params.get_float_texture("tex", 1.)?; let mut scale = params.get_float_texture("scale", 1.)?; for _ in 0..2 { if let FloatTexture::Constant(c_tex) = &*scale { let cs = c_tex.value; if cs == 1.0 { return Ok((*tex).clone()); } else if let FloatTexture::Image(img_tex) = &*tex { let mut image_copy = img_tex.clone(); image_copy.base.multiply_scale(cs); return Ok(FloatTexture::Image(image_copy)); } } std::mem::swap(&mut tex, &mut scale); } std::mem::swap(&mut tex, &mut scale); Ok(FloatTexture::Scaled(FloatScaledTexture::new( tex.clone(), scale.clone(), ))) } } impl FloatTextureTrait for FloatScaledTexture { fn evaluate(&self, ctx: &TextureEvalContext) -> Float { let sc = self.scale.evaluate(ctx); if sc == 0. { return 0.; } self.tex.evaluate(ctx) } } #[derive(Clone, Debug)] pub struct SpectrumScaledTexture { pub tex: Arc, pub scale: Arc, } impl CreateSpectrumTexture for SpectrumScaledTexture { fn create( _render_from_texture: Transform, parameters: TextureParameterDictionary, spectrum_type: SpectrumType, _loc: FileLoc, ) -> Result { let one = Spectrum::Constant(ConstantSpectrum::new(1.0)); let tex = parameters .get_spectrum_texture("tex", Some(one), spectrum_type) .ok_or_else(|| anyhow::anyhow!("{}: missing \"tex\" parameter", _loc))?; let scale = parameters.get_float_texture("scale", 1.0)?; if let FloatTexture::Constant(ref cscale) = *scale { let cs = cscale.value; if cs == 1.0 { return Ok((*tex).clone()); } if let SpectrumTexture::Image(ref image) = *tex { let mut image_copy = image.clone(); image_copy.base.multiply_scale(cs); return Ok(SpectrumTexture::Image(image_copy)); } } Ok(SpectrumTexture::Scaled(SpectrumScaledTexture { tex, scale, })) } } impl SpectrumTextureTrait for SpectrumScaledTexture { fn evaluate(&self, ctx: &TextureEvalContext, lambda: &SampledWavelengths) -> SampledSpectrum { let sc = self.scale.evaluate(ctx); if sc == 0. { return SampledSpectrum::new(0.); } self.tex.evaluate(ctx, lambda) * sc } }