269 lines
9 KiB
Rust
269 lines
9 KiB
Rust
use crate::textures::*;
|
|
use crate::utils::{MIPMap, MIPMapFilterOptions, TextureParameterDictionary};
|
|
use crate::{Arena, FileLoc};
|
|
use anyhow::{Result, anyhow};
|
|
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::spectrum::Spectrum;
|
|
use shared::core::texture::SpectrumType;
|
|
use shared::core::texture::{
|
|
CylindricalMapping, PlanarMapping, PointTransformMapping, SphericalMapping, TextureEvalContext,
|
|
TextureMapping2D, TextureMapping3D, UVMapping,
|
|
};
|
|
use shared::spectra::{SampledSpectrum, SampledWavelengths};
|
|
use shared::textures::{
|
|
FBmTexture, FloatBilerpTexture, FloatCheckerboardTexture, FloatConstantTexture,
|
|
FloatDotsTexture, MarbleTexture, SpectrumBilerpTexture, SpectrumCheckerboardTexture,
|
|
SpectrumConstantTexture, SpectrumDotsTexture, WindyTexture, WrinkledTexture,
|
|
};
|
|
use shared::utils::Transform;
|
|
use std::collections::HashMap;
|
|
use std::sync::{Arc, Mutex, OnceLock};
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub enum FloatTexture {
|
|
Constant(FloatConstantTexture),
|
|
Checkerboard(FloatCheckerboardTexture),
|
|
Dots(FloatDotsTexture),
|
|
FBm(FBmTexture),
|
|
Windy(WindyTexture),
|
|
Wrinkled(WrinkledTexture),
|
|
Mix(FloatMixTexture),
|
|
DirectionMix(FloatDirectionMixTexture),
|
|
// #[device(custom = "upload_image", variant_type = "GPUFloatImageTexture")]
|
|
Scaled(FloatScaledTexture),
|
|
Image(FloatImageTexture),
|
|
Bilerp(FloatBilerpTexture),
|
|
}
|
|
|
|
impl Default for FloatTexture {
|
|
fn default() -> Self {
|
|
FloatTexture::Constant(FloatConstantTexture::new(1.0))
|
|
}
|
|
}
|
|
|
|
pub trait CreateFloatTexture {
|
|
fn create(
|
|
render_from_texture: Transform,
|
|
params: TextureParameterDictionary,
|
|
loc: FileLoc,
|
|
arena: &Arena,
|
|
) -> Result<FloatTexture>;
|
|
}
|
|
|
|
impl FloatTexture {
|
|
pub fn create(
|
|
name: &str,
|
|
render_from_texture: Transform,
|
|
params: TextureParameterDictionary,
|
|
loc: FileLoc,
|
|
arena: &Arena,
|
|
) -> Result<Self> {
|
|
match name {
|
|
"constant" => FloatConstantTexture::create(render_from_texture, params, loc, arena),
|
|
"scale" => FloatScaledTexture::create(&render_from_texture, ¶ms, &loc, arena),
|
|
"mix" => FloatMixTexture::create(&render_from_texture, ¶ms, &loc, arena),
|
|
"directionmix" => {
|
|
FloatDirectionMixTexture::create(&render_from_texture, ¶ms, &loc, arena)
|
|
}
|
|
"bilerp" => FloatBilerpTexture::create(render_from_texture, params, loc, arena),
|
|
"imagemap" => FloatImageTexture::create(render_from_texture, params, loc, arena),
|
|
"checkerboard" => {
|
|
FloatCheckerboardTexture::create(render_from_texture, params, loc, arena)
|
|
}
|
|
"dots" => FloatDotsTexture::create(render_from_texture, params, loc, arena),
|
|
"fbm" => FBmTexture::create(render_from_texture, params, loc, arena),
|
|
"wrinkled" => WrinkledTexture::create(render_from_texture, params, loc, arena),
|
|
"windy" => WindyTexture::create(render_from_texture, params, loc, arena),
|
|
_ => Err(anyhow!("Float texture type '{}' unknown at {}", name, loc)),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub enum SpectrumTexture {
|
|
Constant(SpectrumConstantTexture),
|
|
Checkerboard(SpectrumCheckerboardTexture),
|
|
Dots(SpectrumDotsTexture),
|
|
Image(SpectrumImageTexture),
|
|
Bilerp(SpectrumBilerpTexture),
|
|
Scaled(SpectrumScaledTexture),
|
|
Marble(MarbleTexture),
|
|
Mix(SpectrumMixTexture),
|
|
DirectionMix(SpectrumDirectionMixTexture),
|
|
}
|
|
|
|
/// A bare `Spectrum` used as a texture is always a constant texture. Saves
|
|
/// writing `SpectrumTexture::Constant(SpectrumConstantTexture::new(s))` at every
|
|
/// default-value site.
|
|
impl From<Spectrum> for SpectrumTexture {
|
|
fn from(s: Spectrum) -> Self {
|
|
SpectrumTexture::Constant(SpectrumConstantTexture::new(s))
|
|
}
|
|
}
|
|
|
|
impl From<Float> for FloatTexture {
|
|
fn from(v: Float) -> Self {
|
|
FloatTexture::Constant(FloatConstantTexture::new(v))
|
|
}
|
|
}
|
|
|
|
pub trait CreateSpectrumTexture {
|
|
fn create(
|
|
render_from_texture: Transform,
|
|
parameters: TextureParameterDictionary,
|
|
spectrum_type: SpectrumType,
|
|
loc: FileLoc,
|
|
arena: &Arena,
|
|
) -> Result<SpectrumTexture>;
|
|
}
|
|
|
|
impl SpectrumTexture {
|
|
pub fn create(
|
|
name: &str,
|
|
render_from_texture: Transform,
|
|
params: TextureParameterDictionary,
|
|
spectrum_type: SpectrumType,
|
|
loc: FileLoc,
|
|
arena: &Arena,
|
|
) -> Result<Self> {
|
|
match name {
|
|
"constant" => SpectrumConstantTexture::create(
|
|
render_from_texture,
|
|
params,
|
|
spectrum_type,
|
|
loc,
|
|
arena,
|
|
),
|
|
"scale" => SpectrumScaledTexture::create(
|
|
render_from_texture,
|
|
params,
|
|
spectrum_type,
|
|
loc,
|
|
arena,
|
|
),
|
|
"mix" => {
|
|
SpectrumMixTexture::create(render_from_texture, params, spectrum_type, loc, arena)
|
|
}
|
|
"directionmix" => SpectrumDirectionMixTexture::create(
|
|
render_from_texture,
|
|
params,
|
|
spectrum_type,
|
|
loc,
|
|
arena,
|
|
),
|
|
"bilerp" => SpectrumBilerpTexture::create(
|
|
render_from_texture,
|
|
params,
|
|
spectrum_type,
|
|
loc,
|
|
arena,
|
|
),
|
|
"imagemap" => {
|
|
SpectrumImageTexture::create(render_from_texture, params, spectrum_type, loc, arena)
|
|
}
|
|
"checkerboard" => SpectrumCheckerboardTexture::create(
|
|
render_from_texture,
|
|
params,
|
|
spectrum_type,
|
|
loc,
|
|
arena,
|
|
),
|
|
"dots" => {
|
|
SpectrumDotsTexture::create(render_from_texture, params, spectrum_type, loc, arena)
|
|
}
|
|
"marble" => {
|
|
MarbleTexture::create(render_from_texture, params, spectrum_type, loc, arena)
|
|
}
|
|
_ => Err(anyhow!(
|
|
"Spectrum texture type '{}' unknown at {}",
|
|
name,
|
|
loc
|
|
)),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub trait CreateTextureMapping {
|
|
fn create(
|
|
params: &TextureParameterDictionary,
|
|
render_from_texture: &Transform,
|
|
loc: &FileLoc,
|
|
) -> Result<Self>
|
|
where
|
|
Self: Sized;
|
|
}
|
|
|
|
impl CreateTextureMapping for TextureMapping2D {
|
|
fn create(
|
|
params: &TextureParameterDictionary,
|
|
render_from_texture: &Transform,
|
|
loc: &FileLoc,
|
|
) -> Result<Self>
|
|
where
|
|
Self: Sized,
|
|
{
|
|
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);
|
|
Ok(TextureMapping2D::UV(mapping))
|
|
}
|
|
"spherical" => {
|
|
let mapping = SphericalMapping::new(&render_from_texture.inverse());
|
|
Ok(TextureMapping2D::Spherical(mapping))
|
|
}
|
|
"cylindrical" => {
|
|
let mapping = CylindricalMapping::new(&render_from_texture.inverse());
|
|
Ok(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);
|
|
Ok(TextureMapping2D::Planar(mapping))
|
|
}
|
|
_ => {
|
|
log::error!("{}: 2D texture mapping unknown {}", loc, mtype);
|
|
Ok(TextureMapping2D::UV(UVMapping::default()))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl CreateTextureMapping for TextureMapping3D {
|
|
fn create(
|
|
params: &TextureParameterDictionary,
|
|
render_from_texture: &Transform,
|
|
loc: &FileLoc,
|
|
) -> Result<Self>
|
|
where
|
|
Self: Sized,
|
|
{
|
|
let mapping = PointTransformMapping::new(render_from_texture.inverse());
|
|
Ok(TextureMapping3D::PointTransform(mapping))
|
|
}
|
|
}
|
|
|
|
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,
|
|
}
|