198 lines
6.9 KiB
Rust
198 lines
6.9 KiB
Rust
use crate::textures::*;
|
|
use crate::utils::mipmap::MIPMap;
|
|
use crate::utils::mipmap::MIPMapFilterOptions;
|
|
use crate::utils::{Arena, FileLoc, TextureParameterDictionary};
|
|
use enum_dispatch::enum_dispatch;
|
|
use shared::Float;
|
|
use shared::core::color::ColorEncoding;
|
|
use shared::core::geometry::Vector3f;
|
|
use shared::core::image::WrapMode;
|
|
use shared::core::texture::{
|
|
CylindricalMapping, PlanarMapping, SphericalMapping, TextureEvalContext, TextureMapping2D,
|
|
UVMapping,
|
|
};
|
|
use shared::spectra::{SampledSpectrum, SampledWavelengths};
|
|
use shared::textures::*;
|
|
use shared::utils::Transform;
|
|
use std::collections::HashMap;
|
|
use std::sync::{Arc, Mutex, OnceLock};
|
|
|
|
pub trait FloatTextureTrait {
|
|
fn evaluate(&self, ctx: &TextureEvalContext) -> Float;
|
|
}
|
|
|
|
pub trait SpectrumTextureTrait {
|
|
fn evaluate(&self, _ctx: &TextureEvalContext, _lambda: &SampledWavelengths) -> SampledSpectrum;
|
|
}
|
|
|
|
#[enum_dispatch(FloatTextureTrait)]
|
|
#[derive(Debug, Clone)]
|
|
pub enum FloatTexture {
|
|
Constant(FloatConstantTexture),
|
|
Image(FloatImageTexture),
|
|
Mix(FloatMixTexture),
|
|
DirectionMix(FloatDirectionMixTexture),
|
|
Scaled(FloatScaledTexture),
|
|
Bilerp(FloatBilerpTexture),
|
|
Checkerboard(FloatCheckerboardTexture),
|
|
Dots(FloatDotsTexture),
|
|
FBm(FBmTexture),
|
|
Ptex(FloatPtexTexture),
|
|
Windy(WindyTexture),
|
|
Wrinkled(WrinkledTexture),
|
|
}
|
|
|
|
impl FloatTextureTrait for Arc<FloatTexture> {
|
|
fn evaluate(&self, ctx: &TextureEvalContext) -> Float {
|
|
self.as_ref().evaluate(ctx)
|
|
}
|
|
}
|
|
|
|
impl FloatTexture {
|
|
pub fn create(
|
|
name: &str,
|
|
render_from_texture: &Transform,
|
|
params: &TextureParameterDictionary,
|
|
loc: &FileLoc,
|
|
arena: &mut Arena,
|
|
) -> Result<Self, String> {
|
|
match name {
|
|
"constant" => {
|
|
let tex = FloatConstantTexture::create(render_from_texture, params, loc);
|
|
Ok(FloatTexture::Constant(tex))
|
|
}
|
|
"scale" => Ok(FloatScaledTexture::create(
|
|
render_from_texture,
|
|
params,
|
|
loc,
|
|
arena,
|
|
)),
|
|
"mix" => {
|
|
let tex = FloatMixTexture::create(render_from_texture, params, loc, arena);
|
|
Ok(FloatTexture::Mix(tex))
|
|
}
|
|
"directionmix" => {
|
|
let tex = FloatDirectionMixTexture::create(render_from_texture, params, loc, arena);
|
|
Ok(FloatTexture::DirectionMix(tex))
|
|
}
|
|
"bilerp" => {
|
|
let tex = FloatBilerpTexture::create(render_from_texture, params, loc);
|
|
Ok(FloatTexture::Bilerp(tex))
|
|
}
|
|
"imagemap" => {
|
|
let tex = FloatImageTexture::create(render_from_texture, params, loc);
|
|
Ok(FloatTexture::Image(tex))
|
|
}
|
|
"checkerboard" => {
|
|
let tex = FloatCheckerboardTexture::create(render_from_texture, params, loc);
|
|
Ok(FloatTexture::Checkerboard(tex))
|
|
}
|
|
"dots" => {
|
|
let tex = FloatDotsTexture::create(render_from_texture, params, loc);
|
|
Ok(FloatTexture::Dots(tex))
|
|
}
|
|
"fbm" => {
|
|
let tex = FBmTexture::create(render_from_texture, params, loc);
|
|
Ok(FloatTexture::FBm(tex))
|
|
}
|
|
"wrinkled" => {
|
|
let tex = WrinkledTexture::create(render_from_texture, params, loc);
|
|
Ok(FloatTexture::Wrinkled(tex))
|
|
}
|
|
"windy" => {
|
|
let tex = WindyTexture::create(render_from_texture, params, loc);
|
|
Ok(FloatTexture::Windy(tex))
|
|
}
|
|
"ptex" => {
|
|
let tex = FloatPtexTexture::create(render_from_texture, params, loc);
|
|
Ok(FloatTexture::Ptex(tex))
|
|
}
|
|
_ => Err(format!("Float texture type '{}' unknown at {}", name, loc)),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
#[enum_dispatch(SpectrumTextureTrait)]
|
|
pub enum SpectrumTexture {
|
|
// RGBConstant(RGBConstantTexture),
|
|
// RGBReflectanceConstant(RGBReflectanceConstantTexture),
|
|
Constant(SpectrumConstantTexture),
|
|
Bilerp(SpectrumBilerpTexture),
|
|
Checkerboard(SpectrumCheckerboardTexture),
|
|
Image(SpectrumImageTexture),
|
|
Marble(MarbleTexture),
|
|
Mix(SpectrumMixTexture),
|
|
DirectionMix(SpectrumDirectionMixTexture),
|
|
Dots(SpectrumDotsTexture),
|
|
// Ptex(SpectrumPtexTexture),
|
|
Scaled(SpectrumScaledTexture),
|
|
}
|
|
|
|
impl SpectrumTextureTrait for Arc<SpectrumTexture> {
|
|
fn evaluate(&self, ctx: &TextureEvalContext, lambda: &SampledWavelengths) -> SampledSpectrum {
|
|
self.as_ref().evaluate(ctx, lambda)
|
|
}
|
|
}
|
|
|
|
pub trait CreateTextureMapping {
|
|
fn create(
|
|
params: &TextureParameterDictionary,
|
|
render_from_texture: &Transform,
|
|
loc: &FileLoc,
|
|
) -> Self;
|
|
}
|
|
|
|
impl CreateTextureMapping for TextureMapping2D {
|
|
fn create(
|
|
params: &TextureParameterDictionary,
|
|
render_from_texture: &Transform,
|
|
loc: &FileLoc,
|
|
) -> Self {
|
|
let mtype = params.get_one_string("mapping", "uv");
|
|
match mtype.as_str() {
|
|
"uv" => {
|
|
let su = params.get_one_float("uscale", 1.);
|
|
let sv = params.get_one_float("vscale", 1.);
|
|
let du = params.get_one_float("udelta", 0.);
|
|
let dv = params.get_one_float("vdelta", 0.);
|
|
let mapping = UVMapping::new(su, sv, du, dv);
|
|
TextureMapping2D::UV(mapping)
|
|
}
|
|
"spherical" => {
|
|
let mapping = SphericalMapping::new(&render_from_texture.inverse());
|
|
TextureMapping2D::Spherical(mapping)
|
|
}
|
|
"cylindrical" => {
|
|
let mapping = CylindricalMapping::new(&render_from_texture.inverse());
|
|
TextureMapping2D::Cylindrical(mapping)
|
|
}
|
|
"planar" => {
|
|
let vs = params.get_one_vector3f("v1", Vector3f::new(1., 0., 0.));
|
|
let vt = params.get_one_vector3f("v2", Vector3f::new(0., 1., 0.));
|
|
let ds = params.get_one_float("udelta", 0.);
|
|
let dt = params.get_one_float("vdelta", 0.);
|
|
let mapping = PlanarMapping::new(&render_from_texture.inverse(), vs, vt, ds, dt);
|
|
TextureMapping2D::Planar(mapping)
|
|
}
|
|
_ => {
|
|
log::error!("{}: 2D texture mapping unknown {}", loc, mtype);
|
|
TextureMapping2D::UV(UVMapping::default())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub static TEXTURE_CACHE: OnceLock<Mutex<HashMap<TexInfo, Arc<MIPMap>>>> = OnceLock::new();
|
|
|
|
pub fn get_texture_cache() -> &'static Mutex<HashMap<TexInfo, Arc<MIPMap>>> {
|
|
TEXTURE_CACHE.get_or_init(|| Mutex::new(HashMap::new()))
|
|
}
|
|
|
|
#[derive(Debug, Hash, PartialEq, Eq, Clone)]
|
|
pub struct TexInfo {
|
|
pub filename: String,
|
|
pub filter_options: MIPMapFilterOptions,
|
|
pub wrap_mode: WrapMode,
|
|
pub encoding: ColorEncoding,
|
|
}
|