use crate::Float; use crate::core::color::{RGB, XYZ}; use crate::core::spectrum::SpectrumTrait; use crate::core::texture::{SpectrumType, TextureEvalContext, TextureMapping2D}; use crate::spectra::{ RGBAlbedoSpectrum, RGBColorSpace, RGBIlluminantSpectrum, RGBUnboundedSpectrum, SampledSpectrum, SampledWavelengths, }; /* GPU heavy code, dont know if this will ever work the way Im doing things. * Leaving it here isolated, for careful handling */ #[repr(C)] #[derive(Clone, Debug, Copy)] pub struct GPUSpectrumImageTexture { pub mapping: TextureMapping2D, pub tex_obj: u64, pub scale: Float, pub invert: bool, pub is_single_channel: bool, pub color_space: RGBColorSpace, pub spectrum_type: SpectrumType, } impl GPUSpectrumImageTexture { pub fn evaluate( &self, ctx: &TextureEvalContext, lambda: &SampledWavelengths, ) -> SampledSpectrum { #[cfg(not(feature = "cuda"))] { return SampledSpectrum::zero(); } #[cfg(feature = "cuda")] { use cuda_std::intrinsics; let c = self.mapping.map(ctx); let u = c.st.x(); let v = 1.0 - c.st.y(); let d_p_dx = [c.dsdx, c.dtdx]; let d_p_dy = [c.dsdy, c.dtdy]; let tex_color = if self.is_single_channel { let val: Float = unsafe { intrinsics::tex2d_grad(self.tex_obj, u, v, d_p_dx, d_p_dy) }; RGB::new(val, val, val) } else { let val: [Float; 4] = unsafe { intrinsics::tex2d_grad(self.tex_obj, u, v, d_p_dx, d_p_dy) }; RGB::new(val[0], val[1], val[2]) }; let mut rgb = tex_color * self.scale; if self.invert { rgb = (RGB::new(1.0, 1.0, 1.0) - rgb).clamp_zero(); } match self.spectrum_type { SpectrumType::Unbounded => { RGBUnboundedSpectrum::new(&self.color_space, rgb).sample(lambda) } SpectrumType::Albedo => { RGBAlbedoSpectrum::new(&self.color_space, rgb.clamp(0.0, 1.0)).sample(lambda) } _ => RGBIlluminantSpectrum::new(&self.color_space, rgb).sample(lambda), } } } } #[derive(Debug, Copy, Clone)] pub struct GPUFloatImageTexture { pub mapping: TextureMapping2D, pub tex_obj: u64, pub scale: Float, pub invert: bool, } impl GPUFloatImageTexture { pub fn evaluate(&self, ctx: &TextureEvalContext) -> Float { #[cfg(not(feature = "cuda"))] { return 0.; } #[cfg(feature = "cuda")] { use cuda_std::intrinsics; let c = self.mapping.map(ctx); let u = c.st.x(); let v = 1.0 - c.st.y(); let d_p_dx = [c.dsdx, c.dtdx]; let d_p_dy = [c.dsdy, c.dtdy]; let val: Float = unsafe { intrinsics::tex2d_grad(self.tex_obj, u, v, d_p_dx, d_p_dy) }; if self.invert { return (1. - v).max(0.); } else { return v; } } } }