use std::sync::Arc;
use crate::{Rgb, Texture};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Side {
#[default]
Front,
Back,
Double,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Blending {
#[default]
Normal,
Additive,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Shading {
#[default]
Standard,
Unlit,
ShadowCatcher,
Normals,
}
#[derive(Debug, Clone)]
pub struct Material {
pub shading: Shading,
pub color: Rgb,
pub opacity: f32,
pub metalness: f32,
pub roughness: f32,
pub emissive: Rgb,
pub emissive_intensity: f32,
pub clearcoat: f32,
pub clearcoat_roughness: f32,
pub reflection: f32,
pub env_intensity: f32,
pub flat_shading: bool,
pub side: Side,
pub blending: Blending,
pub transparent: bool,
pub depth_write: bool,
pub map: Option<Arc<Texture>>,
pub emissive_map: Option<Arc<Texture>>,
pub metal_rough_map: Option<Arc<Texture>>,
pub normal_map: Option<Arc<Texture>>,
pub normal_scale: f32,
pub ao_map: Option<Arc<Texture>>,
pub fog: bool,
}
impl Default for Material {
fn default() -> Self {
Self {
shading: Shading::Standard,
color: Rgb::WHITE,
opacity: 1.0,
metalness: 0.0,
roughness: 1.0,
emissive: Rgb::BLACK,
emissive_intensity: 1.0,
clearcoat: 0.0,
clearcoat_roughness: 0.05,
reflection: 0.0,
env_intensity: 1.0,
flat_shading: false,
side: Side::Front,
blending: Blending::Normal,
transparent: false,
depth_write: false,
map: None,
emissive_map: None,
metal_rough_map: None,
normal_map: None,
normal_scale: 1.0,
ao_map: None,
fog: true,
}
}
}
impl Material {
pub fn standard(color: impl Into<Rgb>) -> Self {
Self {
color: color.into(),
roughness: 0.5,
..Default::default()
}
}
pub fn metal(color: impl Into<Rgb>, roughness: f32) -> Self {
Self {
color: color.into(),
metalness: 1.0,
roughness,
..Default::default()
}
}
pub fn unlit(color: impl Into<Rgb>) -> Self {
Self {
shading: Shading::Unlit,
color: color.into(),
..Default::default()
}
}
pub fn glow(color: impl Into<Rgb>, intensity: f32) -> Self {
Self::unlit(color.into() * intensity).additive().no_fog()
}
pub fn shadow_catcher(opacity: f32) -> Self {
Self {
shading: Shading::ShadowCatcher,
opacity,
..Default::default()
}
}
pub fn normals() -> Self {
Self {
shading: Shading::Normals,
..Default::default()
}
}
pub fn color(mut self, color: impl Into<Rgb>) -> Self {
self.color = color.into();
self
}
pub fn metalness(mut self, metalness: f32) -> Self {
self.metalness = metalness;
self
}
pub fn roughness(mut self, roughness: f32) -> Self {
self.roughness = roughness;
self
}
pub fn emissive(mut self, color: impl Into<Rgb>, intensity: f32) -> Self {
self.emissive = color.into();
self.emissive_intensity = intensity;
self
}
pub fn clearcoat(mut self, amount: f32) -> Self {
self.clearcoat = amount;
self
}
pub fn env_intensity(mut self, intensity: f32) -> Self {
self.env_intensity = intensity;
self
}
pub fn reflection(mut self, amount: f32) -> Self {
self.reflection = amount.clamp(0.0, 1.0);
self
}
pub fn opacity(mut self, opacity: f32) -> Self {
self.opacity = opacity;
self
}
pub fn additive(mut self) -> Self {
self.blending = Blending::Additive;
self.transparent = true;
self
}
pub fn transparent(mut self) -> Self {
self.transparent = true;
self
}
pub fn double_sided(self) -> Self {
self.side(Side::Double)
}
pub fn side(mut self, side: Side) -> Self {
self.side = side;
self
}
pub fn flat(mut self) -> Self {
self.flat_shading = true;
self
}
pub fn map(mut self, texture: impl Into<Arc<Texture>>) -> Self {
self.map = Some(texture.into());
self
}
pub fn emissive_map(mut self, texture: impl Into<Arc<Texture>>) -> Self {
self.emissive_map = Some(texture.into());
self
}
pub fn normal_map(mut self, texture: impl Into<Arc<Texture>>) -> Self {
self.normal_map = Some(texture.into());
self
}
pub fn normal_scale(mut self, scale: f32) -> Self {
self.normal_scale = scale;
self
}
pub fn ao_map(mut self, texture: impl Into<Arc<Texture>>) -> Self {
self.ao_map = Some(texture.into());
self
}
pub fn no_fog(mut self) -> Self {
self.fog = false;
self
}
pub(crate) fn is_blended(&self) -> bool {
self.transparent || self.opacity < 1.0 || self.blending == Blending::Additive
}
}