Add an option to update shadow maps less often
This can be used to improve performance on low-end setups, at the cost of shadows visibly lagging behind for dynamic lights/objects when up close. This option works best with lights that use Reverse Cull Face and a low negative bias value. Co-authored-by: Manuele Finocchiaro <m4nu3lf@gmail.com>
This commit is contained in:
parent
b0cd38b7e3
commit
7d60d68c7e
|
@ -1451,6 +1451,9 @@
|
|||
<member name="rendering/quality/shadows/filter_mode.mobile" type="int" setter="" getter="" default="0">
|
||||
Lower-end override for [member rendering/quality/shadows/filter_mode] on mobile devices, due to performance concerns or driver support.
|
||||
</member>
|
||||
<member name="rendering/quality/shadows/update_every_2_frames" type="bool" setter="" getter="" default="false">
|
||||
If [code]true[/code], directional and point light shadows are only updated every 2 frames instead of being updated every frame. Updates are staggered across frames to avoid stuttering. This improves performance at the cost of shadows updating in a more "choppy" manner, especially at lower framerates. The difference is mainly noticeable with fast-moving lights, especially when close to the camera.
|
||||
</member>
|
||||
<member name="rendering/quality/skinning/force_software_skinning" type="bool" setter="" getter="" default="false">
|
||||
Forces [MeshInstance] to always perform skinning on the CPU (applies to both GLES2 and GLES3).
|
||||
See also [member rendering/quality/skinning/software_skinning_fallback].
|
||||
|
|
|
@ -2641,8 +2641,19 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
|
|||
RID *directional_light_ptr = &light_instance_cull_result[light_cull_count];
|
||||
directional_light_count = 0;
|
||||
|
||||
// directional lights
|
||||
{
|
||||
if (bool(GLOBAL_GET("rendering/quality/shadows/update_every_2_frames"))) {
|
||||
// Toggle between directional and point light shadow updating every frame.
|
||||
// This update staggering avoids stuttering by splitting CPU/GPU load across frames.
|
||||
if (shadow_map_update == ShadowMapUpdate::SHADOW_MAP_UPDATE_DIRECTIONAL) {
|
||||
shadow_map_update = ShadowMapUpdate::SHADOW_MAP_UPDATE_POINT;
|
||||
} else {
|
||||
shadow_map_update = ShadowMapUpdate::SHADOW_MAP_UPDATE_DIRECTIONAL;
|
||||
}
|
||||
} else {
|
||||
shadow_map_update = ShadowMapUpdate::SHADOW_MAP_UPDATE_POINT_AND_DIRECTIONAL;
|
||||
}
|
||||
|
||||
{ // directional lights
|
||||
Instance **lights_with_shadow = (Instance **)alloca(sizeof(Instance *) * scenario->directional_lights.size());
|
||||
int directional_shadow_count = 0;
|
||||
|
||||
|
@ -2668,17 +2679,19 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
|
|||
}
|
||||
}
|
||||
|
||||
VSG::scene_render->set_directional_shadow_count(directional_shadow_count);
|
||||
if (shadow_map_update != ShadowMapUpdate::SHADOW_MAP_UPDATE_POINT) {
|
||||
VSG::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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{ //setup shadow maps
|
||||
|
||||
//SortArray<Instance*,_InstanceLightsort> sorter;
|
||||
//sorter.sort(light_cull_result,light_cull_count);
|
||||
if (shadow_map_update != ShadowMapUpdate::SHADOW_MAP_UPDATE_DIRECTIONAL) {
|
||||
// Set up point light shadow maps.
|
||||
|
||||
for (int i = 0; i < light_cull_count; i++) {
|
||||
Instance *ins = light_cull_result[i];
|
||||
|
||||
|
|
|
@ -54,6 +54,12 @@ public:
|
|||
MAX_EXTERIOR_PORTALS = 128,
|
||||
};
|
||||
|
||||
enum ShadowMapUpdate {
|
||||
SHADOW_MAP_UPDATE_POINT_AND_DIRECTIONAL, // Update both point and directional light shadows for this frame (default).
|
||||
SHADOW_MAP_UPDATE_POINT, // Update point light shadows only for this frame.
|
||||
SHADOW_MAP_UPDATE_DIRECTIONAL, // Update directional light shadows only for this frame.
|
||||
};
|
||||
|
||||
uint64_t render_pass;
|
||||
static VisualServerScene *singleton;
|
||||
|
||||
|
@ -508,6 +514,7 @@ public:
|
|||
int directional_light_count;
|
||||
RID reflection_probe_instance_cull_result[MAX_REFLECTION_PROBES_CULLED];
|
||||
int reflection_probe_cull_count;
|
||||
ShadowMapUpdate shadow_map_update = ShadowMapUpdate::SHADOW_MAP_UPDATE_POINT_AND_DIRECTIONAL;
|
||||
|
||||
RID_Owner<Instance> instance_owner;
|
||||
|
||||
|
|
|
@ -2635,6 +2635,7 @@ VisualServer::VisualServer() {
|
|||
GLOBAL_DEF("rendering/quality/shadows/filter_mode", 1);
|
||||
GLOBAL_DEF("rendering/quality/shadows/filter_mode.mobile", 0);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadows/filter_mode", PropertyInfo(Variant::INT, "rendering/quality/shadows/filter_mode", PROPERTY_HINT_ENUM, "Disabled,PCF5,PCF13"));
|
||||
GLOBAL_DEF("rendering/quality/shadows/update_every_2_frames", false);
|
||||
|
||||
GLOBAL_DEF("rendering/quality/reflections/texture_array_reflections", true);
|
||||
GLOBAL_DEF("rendering/quality/reflections/texture_array_reflections.mobile", false);
|
||||
|
|
Loading…
Reference in a new issue