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>, _named_materials: &HashMap, _loc: &FileLoc, arena: &Arena, ) -> Result { 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>, _named_materials: &HashMap, loc: &FileLoc, arena: &Arena, ) -> Result { 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)) } }