From 9d04826cd3583f9900270c6f74f38caba972f015 Mon Sep 17 00:00:00 2001 From: jitspoe Date: Wed, 20 Mar 2024 23:25:50 -0400 Subject: [PATCH] Fixed shadow fade to actually avoid updating shadows! --- drivers/gles3/storage/light_storage.h | 22 +++++++++++++++++++ .../rendering/dummy/storage/light_storage.h | 1 + .../renderer_rd/storage_rd/light_storage.h | 21 ++++++++++++++++++ servers/rendering/renderer_scene_cull.cpp | 13 +++++++---- servers/rendering/storage/light_storage.h | 1 + 5 files changed, 54 insertions(+), 4 deletions(-) diff --git a/drivers/gles3/storage/light_storage.h b/drivers/gles3/storage/light_storage.h index 2fb4dcaeca1f..f59121ec371c 100644 --- a/drivers/gles3/storage/light_storage.h +++ b/drivers/gles3/storage/light_storage.h @@ -338,6 +338,27 @@ class LightStorage : public RendererLightStorage { return light->shadow; } + virtual bool light_is_shadow_visible_at_position(RID p_light_instance, const Vector3 position) const override { + const LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance); + ERR_FAIL_NULL_V(light_instance, RS::LIGHT_DIRECTIONAL); + const Light *light = light_owner.get_or_null(light_instance->light); + ERR_FAIL_NULL_V(light, RS::LIGHT_DIRECTIONAL); + + if (!light->shadow) { + return false; + } + + if (!light->distance_fade) { + return true; + } + + real_t distance = position.distance_to(light_instance->transform.origin); + + if (distance > light->distance_fade_shadow + light->distance_fade_length) { + return false; + } + } + virtual bool light_has_projector(RID p_light) const override { const Light *light = light_owner.get_or_null(p_light); ERR_FAIL_NULL_V(light, RS::LIGHT_DIRECTIONAL); @@ -444,6 +465,7 @@ class LightStorage : public RendererLightStorage { #ifdef DEBUG_ENABLED ERR_FAIL_COND_V(!shadow_atlas->shadow_owners.has(p_light_instance), 0); #endif + uint32_t key = shadow_atlas->shadow_owners[p_light_instance]; uint32_t quadrant = (key >> QUADRANT_SHIFT) & 0x3; diff --git a/servers/rendering/dummy/storage/light_storage.h b/servers/rendering/dummy/storage/light_storage.h index a9a7beb387ab..9c05f81459f0 100644 --- a/servers/rendering/dummy/storage/light_storage.h +++ b/servers/rendering/dummy/storage/light_storage.h @@ -71,6 +71,7 @@ class LightStorage : public RendererLightStorage { virtual RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) override { return RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; } virtual bool light_has_shadow(RID p_light) const override { return false; } + virtual bool light_is_shadow_visible_at_position(RID p_light_instance, const Vector3 p_position) const { return false; } virtual bool light_has_projector(RID p_light) const override { return false; } virtual RS::LightType light_get_type(RID p_light) const override { return RS::LIGHT_OMNI; } diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h index f5b846362a44..c08013f374e2 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h @@ -544,6 +544,27 @@ class LightStorage : public RendererLightStorage { return light->shadow; } + virtual bool light_is_shadow_visible_at_position(RID p_light_instance, const Vector3 position) const override { + const LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance); + ERR_FAIL_NULL_V(light_instance, RS::LIGHT_DIRECTIONAL); + const Light *light = light_owner.get_or_null(light_instance->light); + ERR_FAIL_NULL_V(light, RS::LIGHT_DIRECTIONAL); + + if (!light->shadow) { + return false; + } + + if (!light->distance_fade) { + return true; + } + + real_t distance = position.distance_to(light_instance->transform.origin); + + if (distance > light->distance_fade_shadow + light->distance_fade_length) { + return false; + } + } + virtual bool light_has_projector(RID p_light) const override { const Light *light = light_owner.get_or_null(p_light); ERR_FAIL_NULL_V(light, RS::LIGHT_DIRECTIONAL); diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 73aacf311f96..0f66d0239821 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -2993,6 +2993,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c Instance *render_reflection_probe = instance_owner.get_or_null(p_reflection_probe); //if null, not rendering to it Scenario *scenario = scenario_owner.get_or_null(p_scenario); + Vector3 camera_position = p_camera_data->main_transform.origin; ERR_FAIL_COND(p_render_buffers.is_null()); @@ -3002,7 +3003,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c if (p_reflection_probe.is_null()) { //no rendering code here, this is only to set up what needs to be done, request regions, etc. - scene_render->sdfgi_update(p_render_buffers, p_environment, p_camera_data->main_transform.origin); //update conditions for SDFGI (whether its used or not) + scene_render->sdfgi_update(p_render_buffers, p_environment, camera_position); //update conditions for SDFGI (whether its used or not) } RENDER_TIMESTAMP("Update Visibility Dependencies"); @@ -3015,7 +3016,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c VisibilityCullData visibility_cull_data; visibility_cull_data.scenario = scenario; visibility_cull_data.viewport_mask = scenario->viewport_visibility_masks[p_viewport]; - visibility_cull_data.camera_position = p_camera_data->main_transform.origin; + visibility_cull_data.camera_position = camera_position; for (int i = scenario->instance_visibility.get_bin_count() - 1; i > 0; i--) { // We skip bin 0 visibility_cull_data.cull_offset = scenario->instance_visibility.get_bin_start(i); @@ -3183,16 +3184,20 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c } } - // Positional Shadowss + // Positional Shadows for (uint32_t i = 0; i < (uint32_t)scene_cull_result.lights.size(); i++) { Instance *ins = scene_cull_result.lights[i]; - if (!p_shadow_atlas.is_valid() || !RSG::light_storage->light_has_shadow(ins->base)) { + if (!p_shadow_atlas.is_valid()) { continue; } InstanceLightData *light = static_cast(ins->base_data); + if (!RSG::light_storage->light_is_shadow_visible_at_position(light->instance, camera_position)) { + continue; + } + float coverage = 0.f; { //compute coverage diff --git a/servers/rendering/storage/light_storage.h b/servers/rendering/storage/light_storage.h index c1f79cfc4924..4eed1a5aeea3 100644 --- a/servers/rendering/storage/light_storage.h +++ b/servers/rendering/storage/light_storage.h @@ -74,6 +74,7 @@ class RendererLightStorage { virtual RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) = 0; virtual bool light_has_shadow(RID p_light) const = 0; + virtual bool light_is_shadow_visible_at_position(RID p_light, const Vector3 p_position) const = 0; virtual bool light_has_projector(RID p_light) const = 0;