use crate::{
core::{
inspect::{Inspect, PropertyInfo},
pool::Handle,
visitor::{Visit, VisitResult, Visitor},
},
scene::{
graph::Graph,
light::{BaseLight, BaseLightBuilder, Light},
node::Node,
},
};
use std::ops::{Deref, DerefMut};
use strum_macros::{AsRefStr, EnumString, EnumVariantNames};
pub const CSM_NUM_CASCADES: usize = 3;
#[derive(Inspect, Clone, Visit, Debug, AsRefStr, EnumString, EnumVariantNames)]
pub enum FrustumSplitOptions {
Absolute {
far_planes: [f32; CSM_NUM_CASCADES],
},
Relative {
fractions: [f32; CSM_NUM_CASCADES],
},
}
impl Default for FrustumSplitOptions {
fn default() -> Self {
Self::Absolute {
far_planes: [5.0, 25.0, 64.0],
}
}
}
#[derive(Inspect, Clone, Visit, Debug)]
pub struct CsmOptions {
pub split_options: FrustumSplitOptions,
#[inspect(min_value = 0.0, step = 0.000025)]
shadow_bias: f32,
}
impl Default for CsmOptions {
fn default() -> Self {
Self {
split_options: Default::default(),
shadow_bias: 0.00025,
}
}
}
impl CsmOptions {
pub fn set_shadow_bias(&mut self, bias: f32) {
self.shadow_bias = bias.max(0.0);
}
pub fn shadow_bias(&self) -> f32 {
self.shadow_bias
}
}
#[derive(Default, Debug, Visit, Inspect)]
pub struct DirectionalLight {
base_light: BaseLight,
#[visit(optional)] pub csm_options: CsmOptions,
}
impl From<BaseLight> for DirectionalLight {
fn from(base_light: BaseLight) -> Self {
Self {
base_light,
csm_options: Default::default(),
}
}
}
impl Deref for DirectionalLight {
type Target = BaseLight;
fn deref(&self) -> &Self::Target {
&self.base_light
}
}
impl DerefMut for DirectionalLight {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.base_light
}
}
impl DirectionalLight {
pub fn raw_copy(&self) -> Self {
Self {
base_light: self.base_light.raw_copy(),
csm_options: self.csm_options.clone(),
}
}
}
pub struct DirectionalLightBuilder {
base_light_builder: BaseLightBuilder,
csm_options: CsmOptions,
}
impl DirectionalLightBuilder {
pub fn new(base_light_builder: BaseLightBuilder) -> Self {
Self {
base_light_builder,
csm_options: Default::default(),
}
}
pub fn build_directional_light(self) -> DirectionalLight {
DirectionalLight {
base_light: self.base_light_builder.build(),
csm_options: self.csm_options,
}
}
pub fn with_csm_options(mut self, csm_options: CsmOptions) -> Self {
self.csm_options = csm_options;
self
}
pub fn build_node(self) -> Node {
Node::Light(Light::Directional(self.build_directional_light()))
}
pub fn build(self, graph: &mut Graph) -> Handle<Node> {
graph.add_node(self.build_node())
}
}