From fe93664cefd3a0f3d8b73bf7fb521e9f35dc3178 Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Tue, 5 Mar 2024 18:59:44 +0100 Subject: [PATCH] EEVEE-Next: Avoid shadowmap padding on 0 radius punctual lights Use the original Light radius to compute the shadowmap projection. Avoid unnecessary padding in shadowmaps, increasing the perceived shadow resolution when the shadow softness is not 0. Pull Request: https://projects.blender.org/blender/blender/pulls/118860 --- .../blender/draw/engines/eevee_next/eevee_light.cc | 13 ++++++++++++- .../blender/draw/engines/eevee_next/eevee_shadow.cc | 7 ++++--- .../blender/draw/engines/eevee_next/eevee_shadow.hh | 6 +++++- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/source/blender/draw/engines/eevee_next/eevee_light.cc b/source/blender/draw/engines/eevee_next/eevee_light.cc index 0a014431798..98dda3a2f7c 100644 --- a/source/blender/draw/engines/eevee_next/eevee_light.cc +++ b/source/blender/draw/engines/eevee_next/eevee_light.cc @@ -97,12 +97,23 @@ void Light::sync(ShadowModule &shadows, const Object *ob, float threshold) /* Reuse shape radius as near clip plane. */ /* This assumes `shape_parameters_set` has already set `radius_squared`. */ float radius = math::sqrt(this->radius_squared); + float shadow_radius = la->shadow_softness_factor * radius; + if (ELEM(la->type, LA_LOCAL, LA_SPOT)) { + /* `shape_parameters_set` can increase the radius of point and spot lights to ensure a + * minimum radius/energy ratio. + * But we don't want to take that into account for computing the shadow-map projection, + * since non-zero radius introduces padding (required for soft-shadows tracing), reducing + * the effective resolution of shadow-maps. + * So we use the original light radius instead. */ + shadow_radius = la->shadow_softness_factor * la->radius; + } this->punctual->sync(this->type, this->object_mat, la->spotsize, radius, this->influence_radius_max, - la->shadow_softness_factor); + la->shadow_softness_factor, + la->shadow_softness_factor * la->radius); } } else { diff --git a/source/blender/draw/engines/eevee_next/eevee_shadow.cc b/source/blender/draw/engines/eevee_next/eevee_shadow.cc index a0c2a55098f..ad0f6db9dca 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shadow.cc +++ b/source/blender/draw/engines/eevee_next/eevee_shadow.cc @@ -224,7 +224,8 @@ void ShadowPunctual::sync(eLightType light_type, float cone_aperture, float light_shape_radius, float max_distance, - float softness_factor) + float softness_factor, + float shadow_radius) { if (is_spot_light(light_type)) { tilemaps_needed_ = (cone_aperture > DEG2RADF(90.0f)) ? 5 : 1; @@ -247,6 +248,7 @@ void ShadowPunctual::sync(eLightType light_type, position_ = float3(object_mat[3]); softness_factor_ = softness_factor; + shadow_radius_ = shadow_radius; } void ShadowPunctual::release_excess_tilemaps() @@ -341,8 +343,7 @@ void ShadowPunctual::end_sync(Light &light, float lod_bias) ShadowTileMapPool &tilemap_pool = shadows_.tilemap_pool; float side, near, far; - compute_projection_boundaries( - light_radius_, light_radius_ * softness_factor_, max_distance_, near, far, side); + compute_projection_boundaries(light_radius_, shadow_radius_, max_distance_, near, far, side); /* Shift shadow map origin for area light to avoid clipping nearby geometry. */ float shift = is_area_light(light.type) ? near : 0.0f; diff --git a/source/blender/draw/engines/eevee_next/eevee_shadow.hh b/source/blender/draw/engines/eevee_next/eevee_shadow.hh index 2ffe6db1ed8..903f4806af7 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shadow.hh +++ b/source/blender/draw/engines/eevee_next/eevee_shadow.hh @@ -395,6 +395,9 @@ class ShadowPunctual : public NonCopyable, NonMovable { int tilemaps_needed_; /** Scaling factor to the light shape for shadow ray casting. */ float softness_factor_; + /** radius * softness_factor (Bypasses LightModule radius modifications to avoid unnecesary + * padding in the shadow projection). */ + float shadow_radius_; public: ShadowPunctual(ShadowModule &module) : shadows_(module){}; @@ -414,7 +417,8 @@ class ShadowPunctual : public NonCopyable, NonMovable { float cone_aperture, float light_shape_radius, float max_distance, - float softness_factor); + float softness_factor, + float shadow_radius); /** * Release the tile-maps that will not be used in the current frame.