pbrt/shared/src/textures/image.rs

105 lines
3.1 KiB
Rust

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;
}
}
}
}