Skip to content

Commit 00186e7

Browse files
committed
Automatically adjust Light3D shadow bias to account for resolution
Higher shadowmap resolutions make it possible to use lower bias values without exhibiting shadow acne. On the other hand, shadow bias should be increased when using lower shadowmap resolutions (but not as much, to avoid peter-panning).
1 parent 8495be9 commit 00186e7

File tree

1 file changed

+29
-11
lines changed

1 file changed

+29
-11
lines changed

servers/rendering/renderer_rd/renderer_scene_render_rd.cpp

+29-11
Original file line numberDiff line numberDiff line change
@@ -3272,6 +3272,11 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
32723272

32733273
r_directional_light_soft_shadows = false;
32743274

3275+
ShadowAtlas *shadow_atlas = nullptr;
3276+
if (p_shadow_atlas.is_valid() && p_using_shadows) {
3277+
shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas);
3278+
}
3279+
32753280
for (int i = 0; i < (int)p_lights.size(); i++) {
32763281
LightInstance *li = light_instance_owner.get_or_null(p_lights[i]);
32773282
if (!li) {
@@ -3419,9 +3424,19 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
34193424
Transform3D modelview = (inverse_transform * li->shadow_transform[j].transform).inverse();
34203425

34213426
CameraMatrix shadow_mtx = rectm * bias * matrix * modelview;
3427+
34223428
light_data.shadow_split_offsets[j] = split;
3423-
float bias_scale = li->shadow_transform[j].bias_scale;
3424-
light_data.shadow_bias[j] = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0 * bias_scale;
3429+
3430+
float bias_scale;
3431+
if (directional_shadow.size < 4096) {
3432+
// For shadow map sizes below the default, don't increase bias too much to avoid peter-panning.
3433+
bias_scale = (1 + li->shadow_transform[j].bias_scale * (4096.0 / MAX(256, directional_shadow.size))) * 0.5;
3434+
} else {
3435+
// Reduce shadow bias for shadow map sizes higher than the default.
3436+
bias_scale = li->shadow_transform[j].bias_scale * (4096.0 / directional_shadow.size);
3437+
}
3438+
3439+
light_data.shadow_bias[j] = (storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) * bias_scale) / 100.0;
34253440
light_data.shadow_normal_bias[j] = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * li->shadow_transform[j].shadow_texel_size;
34263441
light_data.shadow_transmittance_bias[j] = storage->light_get_transmittance_bias(base) * bias_scale;
34273442
light_data.shadow_z_range[j] = li->shadow_transform[j].farplane;
@@ -3499,12 +3514,6 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
34993514
sorter.sort(cluster.spot_light_sort, cluster.spot_light_count);
35003515
}
35013516

3502-
ShadowAtlas *shadow_atlas = nullptr;
3503-
3504-
if (p_shadow_atlas.is_valid() && p_using_shadows) {
3505-
shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas);
3506-
}
3507-
35083517
bool using_forward_ids = _uses_forward_ids();
35093518

35103519
for (uint32_t i = 0; i < (cluster.omni_light_count + cluster.spot_light_count); i++) {
@@ -3594,13 +3603,22 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
35943603
float shadow_texel_size = light_instance_get_shadow_texel_size(li->self, p_shadow_atlas);
35953604
light_data.shadow_normal_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size * 10.0;
35963605

3606+
float bias_resolution_factor;
3607+
if (shadow_atlas->size < 4096) {
3608+
// For shadow map sizes below the default, don't increase bias too much to avoid peter-panning.
3609+
bias_resolution_factor = (1 + (4096.0 / MAX(256, shadow_atlas->size))) * 0.5;
3610+
} else {
3611+
// Reduce shadow bias for shadow map sizes higher than the default.
3612+
bias_resolution_factor = (4096.0 / shadow_atlas->size);
3613+
}
3614+
35973615
if (type == RS::LIGHT_SPOT) {
3598-
light_data.shadow_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0;
3616+
light_data.shadow_bias = (storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0) * bias_resolution_factor;
35993617
} else { //omni
3600-
light_data.shadow_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS);
3618+
light_data.shadow_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) * bias_resolution_factor;
36013619
}
36023620

3603-
light_data.transmittance_bias = storage->light_get_transmittance_bias(base);
3621+
light_data.transmittance_bias = storage->light_get_transmittance_bias(base) * bias_resolution_factor;
36043622

36053623
Vector2i omni_offset;
36063624
Rect2 rect = light_instance_get_shadow_atlas_rect(li->self, p_shadow_atlas, omni_offset);

0 commit comments

Comments
 (0)