From 25d8fbdba4114d929678a431b7886fe34ad2899c Mon Sep 17 00:00:00 2001 From: Relintai Date: Sat, 8 Oct 2022 17:47:22 +0200 Subject: [PATCH] Ported: visual instance layers are regarded during shadow culling. todo: setting Camera cull_mask should mark affected shadows dirty somehow - markusneg https://github.com/godotengine/godot/pull/61841/commits/16517ecb3dc8cc1891964a5dd166ac46cba4e31a --- servers/rendering/rendering_server_scene.cpp | 32 +++++++++++++++----- servers/rendering/rendering_server_scene.h | 2 +- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/servers/rendering/rendering_server_scene.cpp b/servers/rendering/rendering_server_scene.cpp index 259b4dbdb..711235a99 100644 --- a/servers/rendering/rendering_server_scene.cpp +++ b/servers/rendering/rendering_server_scene.cpp @@ -666,7 +666,23 @@ void RenderingServerScene::instance_set_layer_mask(RID p_instance, uint32_t p_ma Instance *instance = instance_owner.get(p_instance); ERR_FAIL_COND(!instance); + if (instance->layer_mask == p_mask) { + return; + } + instance->layer_mask = p_mask; + + // update lights to show / hide shadows according to the new mask + if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) { + InstanceGeometryData *geom = static_cast(instance->base_data); + + if (geom->can_cast_shadows) { + for (List::Element *E = geom->lighting.front(); E; E = E->next()) { + InstanceLightData *light = static_cast(E->get()->base_data); + light->shadow_dirty = true; + } + } + } } void RenderingServerScene::instance_set_pivot_data(RID p_instance, float p_sorting_offset, bool p_use_aabb_center) { @@ -2066,7 +2082,7 @@ void RenderingServerScene::_update_dirty_instance(Instance *p_instance) { p_instance->update_materials = false; } -bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario) { +bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario, uint32_t p_visible_layers) { InstanceLightData *light = static_cast(p_instance->base_data); Transform light_transform = p_instance->transform; @@ -2099,7 +2115,7 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c for (int i = 0; i < cull_count; i++) { Instance *instance = instance_shadow_cull_result[i]; - if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast(instance->base_data)->can_cast_shadows) { + if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask)) { continue; } @@ -2302,7 +2318,7 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c for (int j = 0; j < cull_count; j++) { float min, max; Instance *instance = instance_shadow_cull_result[j]; - if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast(instance->base_data)->can_cast_shadows) { + if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask)) { cull_count--; SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]); j--; @@ -2359,7 +2375,7 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c for (int j = 0; j < cull_count; j++) { Instance *instance = instance_shadow_cull_result[j]; - if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast(instance->base_data)->can_cast_shadows) { + if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask)) { cull_count--; SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]); j--; @@ -2411,7 +2427,7 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c Plane near_plane(xform.origin, -xform.basis.get_axis(2)); for (int j = 0; j < cull_count; j++) { Instance *instance = instance_shadow_cull_result[j]; - if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast(instance->base_data)->can_cast_shadows) { + if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask)) { cull_count--; SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]); j--; @@ -2446,7 +2462,7 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c Plane near_plane(light_transform.origin, -light_transform.basis.get_axis(2)); for (int j = 0; j < cull_count; j++) { Instance *instance = instance_shadow_cull_result[j]; - if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast(instance->base_data)->can_cast_shadows) { + if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask)) { cull_count--; SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]); j--; @@ -2691,7 +2707,7 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const RSG::scene_render->set_directional_shadow_count(directional_shadow_count); for (int i = 0; i < directional_shadow_count; i++) { - _light_instance_update_shadow(lights_with_shadow[i], p_cam_transform, p_cam_projection, p_cam_orthogonal, p_shadow_atlas, scenario); + _light_instance_update_shadow(lights_with_shadow[i], p_cam_transform, p_cam_projection, p_cam_orthogonal, p_shadow_atlas, scenario, p_visible_layers); } } @@ -2787,7 +2803,7 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const if (redraw) { //must redraw! - light->shadow_dirty = _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_shadow_atlas, scenario); + light->shadow_dirty = _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_shadow_atlas, scenario, p_visible_layers); } } } diff --git a/servers/rendering/rendering_server_scene.h b/servers/rendering/rendering_server_scene.h index 85cb49f0b..77b994875 100644 --- a/servers/rendering/rendering_server_scene.h +++ b/servers/rendering/rendering_server_scene.h @@ -707,7 +707,7 @@ public: _FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance); _FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance); - _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario); + _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario, uint32_t p_visible_layers = 0xFFFFFF); void _prepare_scene(const Transform p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int32_t &r_previous_room_id_hint); void _render_scene(const Transform p_cam_transform, const Projection &p_cam_projection, const int p_eye, bool p_cam_orthogonal, RID p_force_environment, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);