EEVEE: Replace angle computation in shadow code with cosine

The tangent computation was not needed. Also precompute the
cosine of the shadow angle to avoid implementation dependant
result.

Pull Request: https://projects.blender.org/blender/blender/pulls/151739
This commit is contained in:
Clément Foucault 2025-12-17 14:45:58 +01:00 • committed by Clément Foucault
parent 2ae058812c
commit 259267952f
5 changed files with 14 additions and 10 deletions

View file

@ -207,6 +207,8 @@ void Light::shape_parameters_set(const ::Light *la,
l_sun.shadow_angle = sun_half_angle * trace_scaling_fac;
/* Clamp to a minimum to distinguish between point lights and area light shadow. */
l_sun.shadow_angle = (sun_half_angle > 0.0f) ? max_ff(1e-8f, l_sun.shadow_angle) : 0.0f;
/* Precompute this cosine on CPU to avoid differences in shadow tracing between platforms. */
l_sun.shadow_angle_cos = cosf(l_sun.shadow_angle);
/* Clamp to minimum value before float imprecision artifacts appear. */
l_sun.shape_radius = clamp(tanf(sun_half_angle), 0.001f, 20.0f);
/* Stable shading direction. */

View file

@ -160,7 +160,7 @@ struct [[host_shared]] LightSunData {
/** Angle covered by the light shape for shadow ray casting. */
float shadow_angle;
float _pad5;
float shadow_angle_cos;
float _pad3;
float _pad4;

View file

@ -157,12 +157,12 @@ ShadowRayDirectional shadow_ray_generate_directional(
float dist_to_near_plane = -lP.z - clip_near;
/* Trace in a radius that is covered by low resolution page inflation. */
float max_tracing_distance = texel_radius * float(SHADOW_PAGE_RES << SHADOW_TILEMAP_LOD);
/* TODO(fclem): Remove atan here. We only need the cosine of the angle. */
float max_tracing_angle = atan_fast(max_tracing_distance / dist_to_near_plane);
float shadow_angle = min(light.sun().shadow_angle, max_tracing_angle);
float max_tracing_angle_cos = cos_from_tan(max_tracing_distance / dist_to_near_plane);
/* Taking max of cosines to get the minimum of the angles. */
float shadow_angle_cos = max(light.sun().shadow_angle_cos, max_tracing_angle_cos);
/* Light shape is 1 unit away from the shading point. */
float3 direction = sample_uniform_cone(random_2d, cos(shadow_angle));
float3 direction = sample_uniform_cone(random_2d, shadow_angle_cos);
/* It only make sense to trace where there can be occluder. Clamp by distance to near plane. */
direction *= max(texel_radius, dist_to_near_plane / direction.z);

View file

@ -121,3 +121,8 @@ float cos_from_sin(float s)
{
return sqrt(max(0.0f, 1.0f - square(s)));
}
float cos_from_tan(float t)
{
return inversesqrt(1.0f + square(t));
}

View file

@ -40,6 +40,8 @@ BLOCKLIST = [
"light_path_is_shadow_ray.blend",
# Blocked as the test seems to alternate between two different states
"light_path_is_diffuse_ray.blend",
# Blocked due to stochastic diffuse/transmission layering resulting in non-deterministic surfel lighting.
"principled_bsdf_transmission.blend",
]
BLOCKLIST_METAL = [
@ -61,11 +63,6 @@ BLOCKLIST_VULKAN = [
]
BLOCKLIST_INTEL = [
# Blocked due to large differences in dithered surfaces and shadows.
"transparency_blended.blend",
"transparency_dithered.blend",
# Blocked due to differences in shadow edges (to be investigated).
"shadow_resolution_scale.blend"
]