summaryrefslogtreecommitdiffstats
path: root/servers/rendering/renderer_scene_cull.h
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering/renderer_scene_cull.h')
-rw-r--r--servers/rendering/renderer_scene_cull.h70
1 files changed, 64 insertions, 6 deletions
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index 4745c3d1d3..f48902a4ef 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -46,6 +46,8 @@
#include "servers/rendering/storage/utilities.h"
#include "servers/xr/xr_interface.h"
+class RenderingLightCuller;
+
class RendererSceneCull : public RenderingMethod {
public:
RendererSceneRender *scene_render = nullptr;
@@ -506,6 +508,9 @@ public:
}
} break;
+ default: {
+ // Ignored notifications.
+ } break;
}
}
@@ -676,7 +681,6 @@ public:
uint64_t last_version;
List<Instance *>::Element *D; // directional light in scenario
- bool shadow_dirty;
bool uses_projector = false;
bool uses_softshadow = false;
@@ -687,12 +691,59 @@ public:
RS::LightBakeMode bake_mode;
uint32_t max_sdfgi_cascade = 2;
+ private:
+ // Instead of a single dirty flag, we maintain a count
+ // so that we can detect lights that are being made dirty
+ // each frame, and switch on tighter caster culling.
+ int32_t shadow_dirty_count;
+
+ uint32_t light_update_frame_id;
+ bool light_intersects_multiple_cameras;
+ uint32_t light_intersects_multiple_cameras_timeout_frame_id;
+
+ public:
+ bool is_shadow_dirty() const { return shadow_dirty_count != 0; }
+ void make_shadow_dirty() { shadow_dirty_count = light_intersects_multiple_cameras ? 1 : 2; }
+ void detect_light_intersects_multiple_cameras(uint32_t p_frame_id) {
+ // We need to detect the case where shadow updates are occurring
+ // more than once per frame. In this case, we need to turn off
+ // tighter caster culling, so situation reverts to one full shadow update
+ // per frame (light_intersects_multiple_cameras is set).
+ if (p_frame_id == light_update_frame_id) {
+ light_intersects_multiple_cameras = true;
+ light_intersects_multiple_cameras_timeout_frame_id = p_frame_id + 60;
+ } else {
+ // When shadow_volume_intersects_multiple_cameras is set, we
+ // want to detect the situation this is no longer the case, via a timeout.
+ // The system can go back to tighter caster culling in this situation.
+ // Having a long-ish timeout prevents rapid cycling.
+ if (light_intersects_multiple_cameras && (p_frame_id >= light_intersects_multiple_cameras_timeout_frame_id)) {
+ light_intersects_multiple_cameras = false;
+ light_intersects_multiple_cameras_timeout_frame_id = UINT32_MAX;
+ }
+ }
+ light_update_frame_id = p_frame_id;
+ }
+
+ void decrement_shadow_dirty() {
+ shadow_dirty_count--;
+ DEV_ASSERT(shadow_dirty_count >= 0);
+ }
+
+ // Shadow updates can either full (everything in the shadow volume)
+ // or closely culled to the camera frustum.
+ bool is_shadow_update_full() const { return shadow_dirty_count == 0; }
+
InstanceLightData() {
bake_mode = RS::LIGHT_BAKE_DISABLED;
- shadow_dirty = true;
D = nullptr;
last_version = 0;
baked_light = nullptr;
+
+ shadow_dirty_count = 1;
+ light_update_frame_id = UINT32_MAX;
+ light_intersects_multiple_cameras_timeout_frame_id = UINT32_MAX;
+ light_intersects_multiple_cameras = false;
}
};
@@ -951,8 +1002,8 @@ public:
uint32_t geometry_instance_pair_mask = 0; // used in traditional forward, unnecessary on clustered
- const int TAA_JITTER_COUNT = 16;
- LocalVector<Vector2> taa_jitter_array;
+ LocalVector<Vector2> camera_jitter_array;
+ RenderingLightCuller *light_culler = nullptr;
virtual RID instance_allocate();
virtual void instance_initialize(RID p_rid);
@@ -1086,7 +1137,7 @@ public:
void _render_scene(const RendererSceneRender::CameraData *p_camera_data, const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, RID p_force_camera_attributes, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows = true, RenderInfo *r_render_info = nullptr);
void render_empty_scene(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_scenario, RID p_shadow_atlas);
- void render_camera(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderingMethod::RenderInfo *r_render_info = nullptr);
+ void render_camera(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, uint32_t p_jitter_phase_count, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderingMethod::RenderInfo *r_render_info = nullptr);
void update_dirty_instances();
void render_particle_colliders();
@@ -1152,7 +1203,7 @@ public:
PASS1RC(float, environment_get_white, RID)
// Fog
- PASS10(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float, float)
+ PASS11(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float, float, RS::EnvironmentFogMode)
PASS1RC(bool, environment_get_fog_enabled, RID)
PASS1RC(Color, environment_get_fog_light_color, RID)
@@ -1163,10 +1214,17 @@ public:
PASS1RC(float, environment_get_fog_height, RID)
PASS1RC(float, environment_get_fog_height_density, RID)
PASS1RC(float, environment_get_fog_aerial_perspective, RID)
+ PASS1RC(RS::EnvironmentFogMode, environment_get_fog_mode, RID)
PASS2(environment_set_volumetric_fog_volume_size, int, int)
PASS1(environment_set_volumetric_fog_filter_active, bool)
+ // Depth Fog
+ PASS4(environment_set_fog_depth, RID, float, float, float)
+ PASS1RC(float, environment_get_fog_depth_curve, RID)
+ PASS1RC(float, environment_get_fog_depth_begin, RID)
+ PASS1RC(float, environment_get_fog_depth_end, RID)
+
// Volumentric Fog
PASS14(environment_set_volumetric_fog, RID, bool, float, const Color &, const Color &, float, float, float, float, float, bool, float, float, float)