#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub enum LightConfig {
Directional {
color: [f32; 3],
intensity: f32,
#[serde(default)]
shadow: LightShadowConfig,
},
Point {
color: [f32; 3],
intensity: f32,
range: f32,
#[serde(default)]
shadow: LightShadowConfig,
},
Spot {
color: [f32; 3],
intensity: f32,
range: f32,
inner_angle: f32,
outer_angle: f32,
#[serde(default)]
shadow: LightShadowConfig,
},
}
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct LightShadowConfig {
#[serde(default = "default_true")]
pub cast: bool,
#[serde(default = "default_depth_bias")]
pub depth_bias: f32,
#[serde(default = "default_normal_bias")]
pub normal_bias: f32,
#[serde(default = "default_shadow_res")]
pub resolution: u32,
#[serde(default)]
pub hardness: LightShadowHardness,
#[serde(default = "default_pcss_scale")]
pub pcss_penumbra_scale: f32,
#[serde(default = "default_max_distance")]
pub max_distance: f32,
#[serde(default = "default_cascades")]
pub cascade_count: u8,
#[serde(default = "default_cascade_lambda")]
pub cascade_split_lambda: f32,
#[serde(default)]
pub evsm_cutoff: EvsmCutoff,
#[serde(default)]
pub far_cascade_update_rate: FarCascadeUpdateRate,
#[serde(default)]
pub cube_face_update_rate: CubeFaceUpdateRate,
}
impl Default for LightShadowConfig {
fn default() -> Self {
Self {
cast: true,
depth_bias: 0.0005,
normal_bias: 0.05,
resolution: 1024,
hardness: LightShadowHardness::Soft,
pcss_penumbra_scale: 1.0,
max_distance: 0.0,
cascade_count: 4,
cascade_split_lambda: 0.5,
evsm_cutoff: EvsmCutoff::LastCascade,
far_cascade_update_rate: FarCascadeUpdateRate::Every4Frames,
cube_face_update_rate: CubeFaceUpdateRate::EveryFrame,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize, Default)]
#[serde(rename_all = "snake_case")]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub enum LightShadowHardness {
Hard,
#[default]
Soft,
Pcss,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize, Default)]
#[serde(rename_all = "snake_case")]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub enum EvsmCutoff {
Off,
#[default]
LastCascade,
LastTwoCascades,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize, Default)]
#[serde(rename_all = "snake_case")]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub enum FarCascadeUpdateRate {
EveryFrame,
Every2Frames,
#[default]
Every4Frames,
Every8Frames,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize, Default)]
#[serde(rename_all = "snake_case")]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub enum CubeFaceUpdateRate {
#[default]
EveryFrame,
Every2Frames,
Every4Frames,
Every8Frames,
}
fn default_true() -> bool {
true
}
fn default_depth_bias() -> f32 {
0.0005
}
fn default_normal_bias() -> f32 {
0.05
}
fn default_shadow_res() -> u32 {
1024
}
fn default_pcss_scale() -> f32 {
1.0
}
fn default_max_distance() -> f32 {
0.0
}
fn default_cascades() -> u8 {
4
}
fn default_cascade_lambda() -> f32 {
0.5
}
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
#[derive(Eq, Hash, Copy)]
pub enum LightKind {
Directional,
Point,
Spot,
}
impl LightConfig {
pub fn kind(&self) -> LightKind {
match self {
Self::Directional { .. } => LightKind::Directional,
Self::Point { .. } => LightKind::Point,
Self::Spot { .. } => LightKind::Spot,
}
}
pub fn shadow(&self) -> &LightShadowConfig {
match self {
Self::Directional { shadow, .. }
| Self::Point { shadow, .. }
| Self::Spot { shadow, .. } => shadow,
}
}
pub fn shadow_mut(&mut self) -> &mut LightShadowConfig {
match self {
Self::Directional { shadow, .. }
| Self::Point { shadow, .. }
| Self::Spot { shadow, .. } => shadow,
}
}
pub fn default_for(kind: LightKind) -> Self {
let shadow = LightShadowConfig::default();
match kind {
LightKind::Directional => Self::Directional {
color: [1.0, 1.0, 1.0],
intensity: 4.0,
shadow: LightShadowConfig {
resolution: 2048,
..shadow.clone()
},
},
LightKind::Point => Self::Point {
color: [1.0, 1.0, 1.0],
intensity: 60.0,
range: 20.0,
shadow: shadow.clone(),
},
LightKind::Spot => Self::Spot {
color: [1.0, 1.0, 1.0],
intensity: 80.0,
range: 25.0,
inner_angle: 0.35,
outer_angle: 0.7,
shadow: LightShadowConfig {
hardness: LightShadowHardness::Hard,
..shadow
},
},
}
}
}