EEVEE-Next: Remove slope and quantization biases
This avoid self intersection during tracing which expect unbiased depth. We compensate by adding a 1.5 shadow pixel offset in the normal direction which is enough to fix most remaining self shadowing. But another bias parameter will likely need to be added anyway. Fixes #121194
This commit is contained in:
@@ -107,6 +107,21 @@ float light_attenuation_common(LightData light, const bool is_directional, vec3
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
float light_shape_radius(LightData light)
|
||||
{
|
||||
|
||||
float radius;
|
||||
if (is_sun_light(light.type)) {
|
||||
return light_sun_data_get(light).radius;
|
||||
}
|
||||
else if (is_area_light(light.type)) {
|
||||
return length(light_area_data_get(light).size);
|
||||
}
|
||||
else {
|
||||
return light_spot_data_get(light).radius;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fade light influence when surface is not facing the light.
|
||||
* This is needed because LTC leaks light at roughness not 0 or 1
|
||||
@@ -126,18 +141,8 @@ float light_attenuation_facing(LightData light,
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
float radius;
|
||||
if (is_sun_light(light.type)) {
|
||||
radius = light_sun_data_get(light).radius;
|
||||
}
|
||||
else if (is_area_light(light.type)) {
|
||||
radius = length(light_area_data_get(light).size);
|
||||
}
|
||||
else {
|
||||
radius = light_spot_data_get(light).radius;
|
||||
}
|
||||
/* Sine of angle between light center and light edge. */
|
||||
float sin_solid_angle = radius / distance_to_light;
|
||||
float sin_solid_angle = light_shape_radius(light) / distance_to_light;
|
||||
/* Sine of angle between light center and shading plane. */
|
||||
float sin_light_angle = dot(L, Ng);
|
||||
/* Do attenuation after the horizon line to avoid harsh cut
|
||||
|
||||
@@ -486,7 +486,10 @@ float shadow_normal_offset(float texel_radius, vec3 Ng, vec3 L)
|
||||
/* TODO: Should we take the light shape into consideration? */
|
||||
float cos_theta = abs(dot(Ng, L));
|
||||
float sin_theta = sqrt(saturate(1.0 - square(cos_theta)));
|
||||
return texel_radius * sin_theta;
|
||||
/* Note that we still bias by one pixel anyway to fight quantization artifacts.
|
||||
* This helps with self intersection of slopped surfaces and gives softer soft shadow (?! why).
|
||||
* FIXME: This is likely to hide some issue, and we need a user facing bias parameter anyway. */
|
||||
return texel_radius * (sin_theta + 3.0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,8 +29,6 @@ void main()
|
||||
* Note that we always need a minimum slope bias of 1 pixel to avoid slanted surfaces aliasing
|
||||
* onto facing surfaces.
|
||||
* IMPORTANT: `fwidth` needs to be inside uniform control flow. */
|
||||
f_depth += fwidth(f_depth) * shadow_flat.filter_radius;
|
||||
|
||||
#ifdef SHADOW_UPDATE_TBDR
|
||||
/* We need to write to `gl_FragDepth` un-conditionally. So we cannot early exit or use discard. */
|
||||
# define discard_result f_depth = 1.0;
|
||||
@@ -86,8 +84,6 @@ void main()
|
||||
ivec3 out_texel = ivec3((page.xy << page_shift) | texel_page, page.z);
|
||||
|
||||
uint u_depth = floatBitsToUint(f_depth);
|
||||
/* Quantization bias. Equivalent to `nextafter()` in C without all the safety. */
|
||||
u_depth += 2;
|
||||
imageAtomicMin(shadow_atlas_img, out_texel, u_depth);
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user