1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//! Cached shadow state carried across frames: the cascade, atlas, and
//! point-shadow bookkeeping read and updated each frame. Transient per-frame
//! data such as the cascade matrices and point-shadow faces is not stored here;
//! it flows through `LightingFrame` instead.
use super::point_shadow_pool::PointShadowPool;
pub(crate) struct ShadowState {
/// Cascade-0 light-space matrix (cached for the ground plane ShadowOnly mode).
pub(crate) last_cascade0_shadow_mat: glam::Mat4,
/// LRU allocator for point-light shadow atlas slots.
pub(crate) point_shadow_pool: PointShadowPool,
/// Monotonic frame counter for point-shadow LRU bookkeeping.
pub(crate) point_shadow_frame: u64,
/// Cascade count from the last prepare.
pub(crate) last_cascade_count: u32,
/// Cascade split distances from the last prepare.
pub(crate) last_cascade_splits: [f32; 4],
/// Shadow frustum half-extent from the last prepare.
pub(crate) last_shadow_extent: f32,
/// Shadow atlas resolution from the last prepare.
pub(crate) last_shadow_atlas_resolution: u32,
/// Whether contact shadows were active on the last prepare.
pub(crate) last_contact_shadow_active: bool,
/// Cascade splits from the last tracing-log emission (to detect changes).
pub(crate) last_logged_cascade_splits: [f32; 4],
/// Shadow atlas uniform from the last prepare.
pub(crate) last_shadow_atlas_uniform: crate::resources::ShadowAtlasUniform,
}
impl ShadowState {
pub(crate) fn new() -> Self {
Self {
last_cascade0_shadow_mat: glam::Mat4::IDENTITY,
point_shadow_pool: PointShadowPool::new(),
point_shadow_frame: 0,
last_cascade_count: 0,
last_cascade_splits: [0.0; 4],
last_shadow_extent: 20.0,
last_shadow_atlas_resolution: 4096,
last_contact_shadow_active: false,
last_logged_cascade_splits: [f32::MAX; 4],
last_shadow_atlas_uniform: bytemuck::Zeroable::zeroed(),
}
}
}