pbrt/src/materials/coated.rs

166 lines
7.2 KiB
Rust

use crate::core::image::Image;
use crate::core::material::CreateMaterial;
use crate::core::texture::SpectrumTexture;
use crate::spectra::data::get_named_spectrum;
use crate::utils::{Arena, FileLoc, TextureParameterDictionary, Upload, parameters::error_exit};
use anyhow::Result;
use shared::core::material::Material;
use shared::core::spectrum::Spectrum;
use shared::core::texture::SpectrumType;
use shared::materials::coated::*;
use shared::spectra::ConstantSpectrum;
use shared::textures::SpectrumConstantTexture;
use std::collections::HashMap;
use std::sync::Arc;
impl CreateMaterial for CoatedDiffuseMaterial {
fn create(
parameters: &TextureParameterDictionary,
normal_map: Option<Arc<Image>>,
_named_materials: &HashMap<String, Material>,
_loc: &FileLoc,
arena: &Arena,
) -> Result<Material> {
let reflectance = parameters
.get_spectrum_texture("reflectance", None, SpectrumType::Albedo)
.unwrap_or(Arc::new(SpectrumTexture::Constant(
SpectrumConstantTexture::new(Spectrum::Constant(ConstantSpectrum::new(0.5))),
)));
let u_roughness = parameters
.get_float_texture_or_null("uroughness")
.unwrap_or_else(|| parameters.get_float_texture("roughness", 0.5));
let v_roughness = parameters
.get_float_texture_or_null("vroughness")
.unwrap_or_else(|| parameters.get_float_texture("roughness", 0.5));
let thickness = parameters.get_float_texture("thickness", 0.01);
let eta = parameters
.get_float_array("eta")
.first()
.map(|&v| Spectrum::Constant(ConstantSpectrum::new(v)))
.or_else(|| parameters.get_one_spectrum("eta", None, SpectrumType::Unbounded))
.unwrap_or_else(|| Spectrum::Constant(ConstantSpectrum::new(1.5)));
let max_depth = parameters.get_one_int("maxdepth", 10);
let n_samples = parameters.get_one_int("nsamples", 1);
let g = parameters.get_float_texture("g", 0.);
let albedo = parameters
.get_spectrum_texture("albedo", None, SpectrumType::Albedo)
.unwrap_or_else(|| {
let default_spectrum = Spectrum::Constant(ConstantSpectrum::new(0.));
SpectrumTexture::Constant(SpectrumConstantTexture::new(default_spectrum)).into()
});
let displacement = parameters.get_float_texture("displacement", 0.);
let remap_roughness = parameters.get_one_bool("remaproughness", true);
let specific = CoatedDiffuseMaterial::new(
reflectance.upload(arena),
u_roughness.upload(arena),
v_roughness.upload(arena),
thickness.upload(arena),
albedo.upload(arena),
g.upload(arena),
eta.upload(arena),
displacement.upload(arena),
normal_map.upload(arena),
remap_roughness,
max_depth as u32,
n_samples as u32,
);
Ok(Material::CoatedDiffuse(specific))
}
}
impl CreateMaterial for CoatedConductorMaterial {
fn create(
parameters: &TextureParameterDictionary,
normal_map: Option<Arc<Image>>,
_named_materials: &HashMap<String, Material>,
loc: &FileLoc,
arena: &Arena,
) -> Result<Material> {
let interface_u_roughness = parameters
.get_float_texture_or_null("interface.uroughness")
.unwrap_or_else(|| parameters.get_float_texture("interface.roughness", 0.));
let interface_v_roughness = parameters
.get_float_texture_or_null("interface.vroughness")
.unwrap_or_else(|| parameters.get_float_texture("interface.vroughness", 0.));
let thickness = parameters.get_float_texture("interface.thickness", 0.01);
let interface_eta: Spectrum = parameters
.get_float_array("interface.eta")
.first()
.map(|&v| Spectrum::Constant(ConstantSpectrum::new(v)))
.or_else(|| parameters.get_one_spectrum("interface.eta", None, SpectrumType::Unbounded))
.unwrap_or_else(|| Spectrum::Constant(ConstantSpectrum::new(1.5)));
let conductor_u_roughness = parameters
.get_float_texture_or_null("conductor.uroughness")
.unwrap_or_else(|| parameters.get_float_texture("conductor.roughness", 0.));
let conductor_v_roughness = parameters
.get_float_texture_or_null("conductor.vroughness")
.unwrap_or_else(|| parameters.get_float_texture("conductor.vroughness", 0.));
let reflectance =
parameters.get_spectrum_texture_or_null("reflectance", SpectrumType::Albedo);
let conductor_eta =
parameters.get_spectrum_texture_or_null("conductor.eta", SpectrumType::Unbounded);
let k = parameters.get_spectrum_texture_or_null("conductor.k", SpectrumType::Unbounded);
let (conductor_eta, k) = match (&reflectance, conductor_eta, k) {
(Some(_), Some(_), _) | (Some(_), _, Some(_)) => {
return Err(error_exit(
Some(loc),
"For the coated conductor material, both \"reflectance\" \
and \"eta\" and \"k\" can't be provided.",
));
}
(None, eta, k) => {
let final_eta = eta.unwrap_or_else(|| {
let s = get_named_spectrum("metal-Cu-eta").expect("Missing copper spectrum");
Arc::new(SpectrumTexture::Constant(SpectrumConstantTexture::new(s)))
});
let final_k = k.unwrap_or_else(|| {
let s = get_named_spectrum("metal-Cu-k").expect("Missing copper spectrum");
Arc::new(SpectrumTexture::Constant(SpectrumConstantTexture::new(s)))
});
(Some(final_eta), Some(final_k))
}
(Some(_), None, None) => (None, None),
};
let max_depth = parameters.get_one_int("maxdepth", 10);
let n_samples = parameters.get_one_int("nsamples", 1);
let g = parameters.get_float_texture("g", 0.);
let albedo = parameters
.get_spectrum_texture("albedo", None, SpectrumType::Albedo)
.unwrap_or_else(|| {
let spectrum = Spectrum::Constant(ConstantSpectrum::new(0.));
SpectrumTexture::Constant(SpectrumConstantTexture::new(spectrum)).into()
});
let displacement = parameters.get_float_texture_or_null("displacement");
let remap_roughness = parameters.get_one_bool("remaproughness", true);
let material = Self::new(
normal_map.upload(arena),
displacement.upload(arena),
interface_u_roughness.upload(arena),
interface_v_roughness.upload(arena),
thickness.upload(arena),
interface_eta.upload(arena),
g.upload(arena),
albedo.upload(arena),
conductor_u_roughness.upload(arena),
conductor_v_roughness.upload(arena),
conductor_eta.upload(arena),
k.upload(arena),
reflectance.upload(arena),
max_depth as u32,
n_samples as u32,
remap_roughness,
);
arena.alloc(material);
Ok(Material::CoatedConductor(material))
}
}