Skip to content

Commit f2c362f

Browse files
committed
Merge branch 'shadow-atlas-churn'
2 parents a4fc7f5 + be768fa commit f2c362f

16 files changed

Lines changed: 800 additions & 368 deletions

File tree

crates/renderide/shaders/passes/backend/world_mesh_radial_shadow_caster.wgsl

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,21 @@
33
//! The raster projection selects the shadow volume and atlas UVs. Fragment depth stores normalized
44
//! radial distance so point and spot shadows compare consistently across their projected views.
55

6-
struct ShadowCasterUniforms {
7-
view_proj_left: mat4x4<f32>,
8-
view_proj_right: mat4x4<f32>,
6+
struct ShadowCasterDraw {
97
model: mat4x4<f32>,
108
normal_matrix: mat3x3<f32>,
9+
_pad: array<vec4<f32>, 25>,
10+
}
11+
12+
struct ShadowLayerUniforms {
13+
view_proj: mat4x4<f32>,
1114
light_position_range: vec4<f32>,
1215
shadow_params: vec4<f32>,
13-
_pad: array<vec4<f32>, 15>,
16+
_pad: array<vec4<f32>, 26>,
1417
}
1518

16-
@group(0) @binding(0) var<storage, read> instances: array<ShadowCasterUniforms>;
19+
@group(0) @binding(0) var<storage, read> instances: array<ShadowCasterDraw>;
20+
@group(1) @binding(0) var<uniform> shadow_layer: ShadowLayerUniforms;
1721

1822
struct VertexOutput {
1923
@builtin(position) clip_pos: vec4<f32>,
@@ -30,17 +34,16 @@ fn vs_main(
3034
let world_p = draw.model * vec4<f32>(pos.xyz, 1.0);
3135

3236
var out: VertexOutput;
33-
out.clip_pos = draw.view_proj_left * world_p;
37+
out.clip_pos = shadow_layer.view_proj * world_p;
3438
out.world_pos = world_p.xyz;
3539
out.instance_index = instance_index;
3640
return out;
3741
}
3842

3943
@fragment
4044
fn fs_main(in: VertexOutput) -> @builtin(frag_depth) f32 {
41-
let draw = instances[in.instance_index];
42-
let range = max(draw.light_position_range.w, 0.001);
43-
let bias = max(draw.shadow_params.x, 0.0);
44-
let radial_depth = (length(in.world_pos - draw.light_position_range.xyz) + bias) / range;
45+
let range = max(shadow_layer.light_position_range.w, 0.001);
46+
let bias = max(shadow_layer.shadow_params.x, 0.0);
47+
let radial_depth = (length(in.world_pos - shadow_layer.light_position_range.xyz) + bias) / range;
4548
return clamp(radial_depth, 0.0, 1.0);
4649
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//! Projected shadow caster for world meshes.
2+
//!
3+
//! Per-draw rows carry only model data. The active shadow-view projection is bound once per atlas
4+
//! layer so cascades and cubemap faces can reuse the same caster slab.
5+
6+
struct ShadowCasterDraw {
7+
model: mat4x4<f32>,
8+
normal_matrix: mat3x3<f32>,
9+
_pad: array<vec4<f32>, 25>,
10+
}
11+
12+
struct ShadowLayerUniforms {
13+
view_proj: mat4x4<f32>,
14+
light_position_range: vec4<f32>,
15+
shadow_params: vec4<f32>,
16+
_pad: array<vec4<f32>, 26>,
17+
}
18+
19+
@group(0) @binding(0) var<storage, read> instances: array<ShadowCasterDraw>;
20+
@group(1) @binding(0) var<uniform> shadow_layer: ShadowLayerUniforms;
21+
22+
struct VertexOutput {
23+
@builtin(position) clip_pos: vec4<f32>,
24+
}
25+
26+
@vertex
27+
fn vs_main(
28+
@builtin(instance_index) instance_index: u32,
29+
@location(0) pos: vec4<f32>,
30+
) -> VertexOutput {
31+
let draw = instances[instance_index];
32+
let world_p = draw.model * vec4<f32>(pos.xyz, 1.0);
33+
34+
var out: VertexOutput;
35+
out.clip_pos = shadow_layer.view_proj * world_p;
36+
return out;
37+
}
38+
39+
@fragment
40+
fn fs_main() {
41+
}

0 commit comments

Comments
 (0)