pbrt/src/core/material.rs
2026-05-20 20:14:58 +01:00

106 lines
3.5 KiB
Rust

use crate::Arena;
use crate::core::image::HostImage;
use crate::utils::TextureParameterDictionary;
use crate::utils::error::FileLoc;
use anyhow::{Result, anyhow};
use shared::core::material::Material;
use shared::materials::*;
use std::collections::HashMap;
use std::sync::Arc;
pub trait CreateMaterial: Sized {
fn create(
parameters: &TextureParameterDictionary,
normal_map: Option<Arc<HostImage>>,
named_materials: &HashMap<String, Material>,
loc: &FileLoc,
arena: &Arena,
) -> Result<Material>;
}
pub trait MaterialFactory {
fn create(
name: &str,
params: &TextureParameterDictionary,
normal_map: Option<Arc<HostImage>>,
named_materials: &HashMap<String, Material>,
loc: FileLoc,
arena: &Arena,
) -> Result<Self>
where
Self: Sized;
}
impl MaterialFactory for Material {
fn create(
name: &str,
parameters: &TextureParameterDictionary,
normal_map: Option<Arc<HostImage>>,
named_materials: &HashMap<String, Material>,
loc: FileLoc,
arena: &Arena,
) -> Result<Self>
where
Self: Sized,
{
match name {
"diffuse" => {
DiffuseMaterial::create(parameters, normal_map, named_materials, &loc, arena)
}
"coateddiffuse" => {
CoatedDiffuseMaterial::create(parameters, normal_map, named_materials, &loc, arena)
}
"coatedconductor" => CoatedConductorMaterial::create(
parameters,
normal_map,
named_materials,
&loc,
arena,
),
"diffusetransmission" => DiffuseTransmissionMaterial::create(
parameters,
normal_map,
named_materials,
&loc,
arena,
),
"dielectric" => {
DielectricMaterial::create(parameters, normal_map, named_materials, &loc, arena)
}
"thindielectric" => {
ThinDielectricMaterial::create(parameters, normal_map, named_materials, &loc, arena)
}
"hair" => HairMaterial::create(parameters, normal_map, named_materials, &loc, arena),
"conductor" => {
ConductorMaterial::create(parameters, normal_map, named_materials, &loc, arena)
}
"measured" => {
MeasuredMaterial::create(parameters, normal_map, named_materials, &loc, arena)
}
"subsurface" => {
SubsurfaceMaterial::create(parameters, normal_map, named_materials, &loc, arena)
}
"mix" => MixMaterial::create(parameters, normal_map, named_materials, &loc, arena),
_ => Err(anyhow!("Material type '{}' unknown at {}", name, &loc)),
}
}
}
pub fn default_diffuse_material(arena: &Arena) -> Material {
use shared::core::texture::GPUSpectrumTexture;
use shared::core::texture::SpectrumConstantTexture;
use shared::core::spectrum::{ConstantSpectrum, Spectrum};
use shared::materials::DiffuseMaterial;
use shared::utils::Ptr;
let grey = Spectrum::Constant(ConstantSpectrum { c: 0.5 });
let tex = GPUSpectrumTexture::Constant(SpectrumConstantTexture::new(grey));
let tex_ptr = arena.alloc(tex);
Material::Diffuse(DiffuseMaterial {
normal_map: Ptr::null(),
displacement: Ptr::null(),
reflectance: tex_ptr,
})
}