use std::path::Path; use miette::IntoDiagnostic; use super::*; #[derive(Debug)] pub(super) enum ImageMapWrap { Repeat, Black, Clamp, } impl ImageMapWrap { pub(super) fn new(x: String) -> Result { match x.as_str() { "repeat" => Ok(Self::Repeat), "black" => Ok(Self::Black), "clamp" => Ok(Self::Clamp), _ => Err(miette!("error image map wrap")), } } } #[derive(Debug)] pub(super) enum ImageMapEncoding { #[allow(clippy::upper_case_acronyms)] SRGB, Linear, Gamma(Float), } impl ImageMapEncoding { pub(super) fn new(x: String) -> Result { match x.as_str() { "sRGB" => Ok(Self::SRGB), "linear" => Ok(Self::Linear), s if s.starts_with("gamma ") => { Ok(Self::Gamma(s.split_at(7).1.parse().into_diagnostic()?)) } _ => Err(miette!("error image map encoding")), } } } pub(super) struct SpectrumImageMapTexture { mapping: UVMapping, scale: Float, wrap: ImageMapWrap, invert: bool, image: image::Rgb32FImage, } impl std::fmt::Debug for SpectrumImageMapTexture { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("SpectrumImageMapTexture") .field("mapping", &self.mapping) .field("scale", &self.scale) .field("wrap", &self.wrap) .field("invert", &self.invert) .field("image", &"image data") .finish() } } fn srgb_nonlinear(x: f32) -> f32 { if x <= 0.04045 { x / 12.92 } else { ((x + 0.055) / 1.055).powf(2.4) } } impl SpectrumImageMapTexture { pub(super) fn new( mapping: UVMapping, scale: Float, wrap: ImageMapWrap, encoding: ImageMapEncoding, invert: bool, path: impl AsRef, ) -> Result { let image = image::open(path).unwrap(); let mut image = image.into_rgb32f(); match encoding { ImageMapEncoding::SRGB => { for pixel in image.pixels_mut() { pixel.0 = [ srgb_nonlinear(pixel.0[0]), srgb_nonlinear(pixel.0[1]), srgb_nonlinear(pixel.0[2]), ]; } } ImageMapEncoding::Linear => (), ImageMapEncoding::Gamma(gamma) => { for pixel in image.pixels_mut() { pixel.0 = [ pixel.0[0].powf(gamma), pixel.0[1].powf(gamma), pixel.0[2].powf(gamma), ]; } } } Ok(Self { mapping, scale, invert, wrap, image, }) } } impl Pbrt2dSpectrumTexture for SpectrumImageMapTexture { fn get(&self, u: Float, v: Float) -> Color { let (u, v) = self.mapping.map(u, v); let (w, h) = self.image.dimensions(); dbg!(u, v, w, h); todo!() } } impl PbrtTexture for SpectrumImageMapTexture { fn get_2d_float_texture(self: Arc) -> Result> { Err(miette!("Unable to use this texture as a float texture")) } fn get_2d_spectrum_texture(self: Arc) -> Result> { Ok(self) } fn get_dimension(&self) -> TextureDimension { TextureDimension::D2 } }