use sciforge::hub::prelude::constants::elements::{atomic_mass, electronegativity};
#[derive(Debug, Clone)]
pub struct PbrMaterial {
pub name: &'static str,
pub albedo: [f32; 4],
pub roughness: f32,
pub metallic: f32,
pub normal_strength: f32,
pub emissive: [f32; 3],
pub ior: f32,
pub subsurface: f32,
}
fn metallic_from_iron(fe_wt_frac: f64) -> f32 {
let m_fe = atomic_mass(26);
let m_o = atomic_mass(8);
let fe_fraction_in_feo = m_fe / (m_fe + m_o);
let pure_fe = fe_wt_frac * fe_fraction_in_feo;
let en = electronegativity(26).unwrap_or(1.83);
let metallic_scale = (1.0 - en / 4.0).max(0.0);
(pure_fe * metallic_scale).clamp(0.0, 1.0) as f32
}
impl PbrMaterial {
pub fn ammonia_cloud() -> Self {
Self {
name: "ammonia_cloud",
albedo: [0.90, 0.85, 0.70, 0.8],
roughness: 0.25,
metallic: 0.0,
normal_strength: 0.3,
emissive: [0.0; 3],
ior: 1.325,
subsurface: 0.7,
}
}
pub fn nh4sh_cloud() -> Self {
Self {
name: "nh4sh_cloud",
albedo: [0.70, 0.55, 0.35, 0.85],
roughness: 0.4,
metallic: 0.0,
normal_strength: 0.5,
emissive: [0.0; 3],
ior: 1.40,
subsurface: 0.5,
}
}
pub fn deep_atmosphere() -> Self {
Self {
name: "deep_atmosphere",
albedo: [0.15, 0.10, 0.05, 1.0],
roughness: 0.1,
metallic: 0.01,
normal_strength: 0.2,
emissive: [0.0; 3],
ior: 1.20,
subsurface: 0.0,
}
}
pub fn haze_layer() -> Self {
Self {
name: "haze_layer",
albedo: [0.80, 0.75, 0.60, 0.35],
roughness: 0.1,
metallic: 0.0,
normal_strength: 0.1,
emissive: [0.0; 3],
ior: 1.10,
subsurface: 0.9,
}
}
pub fn core_rock() -> Self {
Self {
name: "core_rock",
albedo: [0.25, 0.20, 0.15, 1.0],
roughness: 0.95,
metallic: metallic_from_iron(0.20),
normal_strength: 1.0,
emissive: [0.0; 3],
ior: 1.55,
subsurface: 0.0,
}
}
pub fn metallic_hydrogen() -> Self {
Self {
name: "metallic_hydrogen",
albedo: [0.55, 0.55, 0.55, 0.95],
roughness: 0.05,
metallic: 0.85,
normal_strength: 0.3,
emissive: [0.005, 0.005, 0.008],
ior: 2.50,
subsurface: 0.0,
}
}
pub fn storm_region() -> Self {
Self {
name: "storm_region",
albedo: [0.55, 0.30, 0.15, 1.0],
roughness: 0.35,
metallic: 0.0,
normal_strength: 0.9,
emissive: [0.0; 3],
ior: 1.33,
subsurface: 0.2,
}
}
pub fn fresnel_r0(&self) -> f64 {
let n = self.ior as f64;
((n - 1.0) / (n + 1.0)).powi(2)
}
pub fn all_jupiter() -> Vec<Self> {
vec![
Self::ammonia_cloud(),
Self::nh4sh_cloud(),
Self::deep_atmosphere(),
Self::haze_layer(),
Self::core_rock(),
Self::metallic_hydrogen(),
Self::storm_region(),
]
}
}