@@ -95,16 +95,16 @@ struct PointLight {
95
95
radius : f32 ;
96
96
near : f32 ;
97
97
far : f32 ;
98
- shadow_bias_min : f32 ;
99
- shadow_bias_max : f32 ;
98
+ shadow_depth_bias : f32 ;
99
+ shadow_normal_bias : f32 ;
100
100
};
101
101
102
102
struct DirectionalLight {
103
103
view_projection : mat4x4 <f32 >;
104
104
color : vec4 <f32 >;
105
105
direction_to_light : vec3 <f32 >;
106
- shadow_bias_min : f32 ;
107
- shadow_bias_max : f32 ;
106
+ shadow_depth_bias : f32 ;
107
+ shadow_normal_bias : f32 ;
108
108
};
109
109
110
110
[[block ]]
@@ -379,7 +379,7 @@ fn directional_light(light: DirectionalLight, roughness: f32, NdotV: f32, normal
379
379
return (specular_light + diffuse ) * light . color. rgb * NoL ;
380
380
}
381
381
382
- fn fetch_point_shadow (light_id : i32 , frag_position : vec4 <f32 >, shadow_bias : f32 ) -> f32 {
382
+ fn fetch_point_shadow (light_id : i32 , frag_position : vec4 <f32 >) -> f32 {
383
383
let light = lights . point_lights[light_id ];
384
384
385
385
// because the shadow maps align with the axes and the frustum planes are at 45 degrees
@@ -412,11 +412,12 @@ fn fetch_point_shadow(light_id: i32, frag_position: vec4<f32>, shadow_bias: f32)
412
412
// a quad (2x2 fragments) being processed not being sampled, and this messing with
413
413
// mip-mapping functionality. The shadow maps have no mipmaps so Level just samples
414
414
// from LOD 0.
415
- let bias = 0.0001 ;
416
- return textureSampleCompareLevel (point_shadow_textures , point_shadow_textures_sampler , frag_ls , i32 (light_id ), depth - shadow_bias );
415
+ return textureSampleCompareLevel (point_shadow_textures , point_shadow_textures_sampler , frag_ls , i32 (light_id ), depth );
417
416
}
418
417
419
- fn fetch_directional_shadow (light_id : i32 , homogeneous_coords : vec4 <f32 >, shadow_bias : f32 ) -> f32 {
418
+ fn fetch_directional_shadow (light_id : i32 , frag_position : vec4 <f32 >) -> f32 {
419
+ let light = lights . directional_lights[light_id ];
420
+ let homogeneous_coords = light . view_projection * frag_position ;
420
421
if (homogeneous_coords . w <= 0.0 ) {
421
422
return 1.0 ;
422
423
}
@@ -428,7 +429,7 @@ fn fetch_directional_shadow(light_id: i32, homogeneous_coords: vec4<f32>, shadow
428
429
// do the lookup, using HW PCF and comparison
429
430
// NOTE: Due to non-uniform control flow above, we must use the level variant of the texture
430
431
// sampler to avoid use of implicit derivatives causing possible undefined behavior.
431
- return textureSampleCompareLevel (directional_shadow_textures , directional_shadow_textures_sampler , light_local , i32 (light_id ), homogeneous_coords . z * proj_correction - shadow_bias );
432
+ return textureSampleCompareLevel (directional_shadow_textures , directional_shadow_textures_sampler , light_local , i32 (light_id ), homogeneous_coords . z * proj_correction );
432
433
}
433
434
434
435
struct FragmentInput {
@@ -521,23 +522,27 @@ fn fragment(in: FragmentInput) -> [[location(0)]] vec4<f32> {
521
522
let n_directional_lights = i32 (lights . n_directional_lights);
522
523
for (var i : i32 = 0 ; i < n_point_lights ; i = i + 1 ) {
523
524
let light = lights . point_lights[i ];
524
- let light_contrib = point_light ( in . world_position . xyz, light , roughness , NdotV , N , V , R , F0 , diffuse_color );
525
+
525
526
let dir_to_light = normalize (light . position. xyz - in . world_position. xyz);
526
- let shadow_bias = max (
527
- light . shadow_bias_max * (1.0 - dot (in . world_normal, dir_to_light )),
528
- light . shadow_bias_min
529
- );
530
- let shadow = fetch_point_shadow (i , in . world_position, shadow_bias );
527
+ let depth_bias = light . shadow_depth_bias * dir_to_light . xyz;
528
+ let NdotL = dot (dir_to_light . xyz, in . world_normal. xyz);
529
+ let normal_bias = light . shadow_normal_bias * (1.0 - NdotL ) * in . world_normal. xyz;
530
+ let biased_position = vec4 <f32 >(in . world_position. xyz + depth_bias + normal_bias , in . world_position. w);
531
+
532
+ let shadow = fetch_point_shadow (i , biased_position );
533
+ let light_contrib = point_light (in . world_position. xyz, light , roughness , NdotV , N , V , R , F0 , diffuse_color );
531
534
light_accum = light_accum + light_contrib * shadow ;
532
535
}
533
536
for (var i : i32 = 0 ; i < n_directional_lights ; i = i + 1 ) {
534
537
let light = lights . directional_lights[i ];
538
+
539
+ let depth_bias = light . shadow_depth_bias * light . direction_to_light. xyz;
540
+ let NdotL = dot (light . direction_to_light. xyz, in . world_normal. xyz);
541
+ let normal_bias = light . shadow_normal_bias * (1.0 - NdotL ) * in . world_normal. xyz;
542
+ let biased_position = vec4 <f32 >(in . world_position. xyz + depth_bias + normal_bias , in . world_position. w);
543
+
544
+ let shadow = fetch_directional_shadow (i , biased_position );
535
545
let light_contrib = directional_light (light , roughness , NdotV , N , V , R , F0 , diffuse_color );
536
- let shadow_bias = max (
537
- light . shadow_bias_max * (1.0 - dot (in . world_normal, light . direction_to_light. xyz)),
538
- light . shadow_bias_min
539
- );
540
- let shadow = fetch_directional_shadow (i , light . view_projection * in . world_position, shadow_bias );
541
546
light_accum = light_accum + light_contrib * shadow ;
542
547
}
543
548
0 commit comments