141 lines
3.5 KiB
Rust
141 lines
3.5 KiB
Rust
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<Self> {
|
|
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<Self> {
|
|
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<Path>,
|
|
) -> Result<Self> {
|
|
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<Self>) -> Result<Arc<dyn Pbrt2dFloatTexture>> {
|
|
Err(miette!("Unable to use this texture as a float texture"))
|
|
}
|
|
|
|
fn get_2d_spectrum_texture(self: Arc<Self>) -> Result<Arc<dyn Pbrt2dSpectrumTexture>> {
|
|
Ok(self)
|
|
}
|
|
|
|
fn get_dimension(&self) -> TextureDimension {
|
|
TextureDimension::D2
|
|
}
|
|
}
|