diff --git a/doc/classes/DirectionalLight.xml b/doc/classes/DirectionalLight.xml index 11c3b7766b9..8496d3f19e9 100644 --- a/doc/classes/DirectionalLight.xml +++ b/doc/classes/DirectionalLight.xml @@ -24,7 +24,7 @@ The maximum distance for shadow splits. Increasing this value will make directional shadows visible from further away, at the cost of lower overall shadow detail and performance (since more objects need to be included in the directional shadow rendering). - + The light's shadow rendering algorithm. See [enum ShadowMode]. @@ -48,7 +48,10 @@ Splits the view frustum in 2 areas, each with its own shadow map. This shadow mode is a compromise between [constant SHADOW_ORTHOGONAL] and [constant SHADOW_PARALLEL_4_SPLITS] in terms of performance. - + + Splits the view frustum in 3 areas, each with its own shadow map. This shadow mode is a compromise between [constant SHADOW_ORTHOGONAL] and [constant SHADOW_PARALLEL_4_SPLITS] in terms of performance. + + Splits the view frustum in 4 areas, each with its own shadow map. This is the slowest directional shadow mode. diff --git a/doc/classes/VisualServer.xml b/doc/classes/VisualServer.xml index abe44ca3b90..4e387bc07b9 100644 --- a/doc/classes/VisualServer.xml +++ b/doc/classes/VisualServer.xml @@ -3581,7 +3581,10 @@ Use 2 splits for shadow projection when using directional light. - + + Use 3 splits for shadow projection when using directional light. + + Use 4 splits for shadow projection when using directional light. diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp index c685deddabf..e28c7326385 100644 --- a/drivers/gles2/rasterizer_scene_gles2.cpp +++ b/drivers/gles2/rasterizer_scene_gles2.cpp @@ -514,6 +514,7 @@ int RasterizerSceneGLES2::get_directional_light_shadow_size(RID p_light_intance) case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: break; //none case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS: case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: shadow_size /= 2; break; @@ -1915,6 +1916,7 @@ void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_OMNI, false); state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_SPOT, false); state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, false); + state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM3, false); state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, false); state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, false); @@ -1936,6 +1938,9 @@ void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, true); } break; + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS: { + state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM3, true); + } break; case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: { state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, true); } break; @@ -2023,6 +2028,10 @@ void RasterizerSceneGLES2::_setup_light(LightInstance *light, ShadowAtlas *shado shadow_count = 2; } break; + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS: { + shadow_count = 3; + } break; + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: { shadow_count = 4; } break; @@ -2034,7 +2043,7 @@ void RasterizerSceneGLES2::_setup_light(LightInstance *light, ShadowAtlas *shado uint32_t width = light->directional_rect.size.x; uint32_t height = light->directional_rect.size.y; - if (light_ptr->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { + if (light_ptr->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS || light_ptr->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { width /= 2; height /= 2; @@ -2670,6 +2679,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, state.scene_shader.set_conditional(SceneShaderGLES2::USE_INSTANCING, false); state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, false); state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, false); + state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM3, false); state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, false); state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, false); state.scene_shader.set_conditional(SceneShaderGLES2::USE_VERTEX_LIGHTING, false); @@ -3717,7 +3727,7 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_ width = light_instance->directional_rect.size.width; height = light_instance->directional_rect.size.height; - if (light->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { + if (light->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS || light->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { width /= 2; height /= 2; diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl index a41cda80e1f..1eb754671b8 100644 --- a/drivers/gles2/shaders/scene.glsl +++ b/drivers/gles2/shaders/scene.glsl @@ -166,18 +166,19 @@ uniform highp float shadow_dual_paraboloid_render_side; uniform highp mat4 light_shadow_matrix; varying highp vec4 shadow_coord; -#if defined(LIGHT_USE_PSSM2) || defined(LIGHT_USE_PSSM4) +#if defined(LIGHT_USE_PSSM2) || defined(LIGHT_USE_PSSM3) || defined(LIGHT_USE_PSSM4) uniform highp mat4 light_shadow_matrix2; varying highp vec4 shadow_coord2; #endif -#if defined(LIGHT_USE_PSSM4) - +#if defined(LIGHT_USE_PSSM3) || defined(LIGHT_USE_PSSM4) uniform highp mat4 light_shadow_matrix3; -uniform highp mat4 light_shadow_matrix4; varying highp vec4 shadow_coord3; -varying highp vec4 shadow_coord4; +#endif +#if defined(LIGHT_USE_PSSM4) +uniform highp mat4 light_shadow_matrix4; +varying highp vec4 shadow_coord4; #endif #endif @@ -625,14 +626,16 @@ VERTEX_SHADER_CODE vec4 vi4 = vec4(vertex_interp, 1.0); shadow_coord = light_shadow_matrix * vi4; -#if defined(LIGHT_USE_PSSM2) || defined(LIGHT_USE_PSSM4) +#if defined(LIGHT_USE_PSSM2) || defined(LIGHT_USE_PSSM3) || defined(LIGHT_USE_PSSM4) shadow_coord2 = light_shadow_matrix2 * vi4; #endif -#if defined(LIGHT_USE_PSSM4) +#if defined(LIGHT_USE_PSSM3) || defined(LIGHT_USE_PSSM4) shadow_coord3 = light_shadow_matrix3 * vi4; - shadow_coord4 = light_shadow_matrix4 * vi4; +#endif +#if defined(LIGHT_USE_PSSM4) + shadow_coord4 = light_shadow_matrix4 * vi4; #endif #endif //use shadow and use lighting @@ -1078,15 +1081,19 @@ uniform highp vec4 light_split_offsets; varying highp vec4 shadow_coord; -#if defined(LIGHT_USE_PSSM2) || defined(LIGHT_USE_PSSM4) +#if defined(LIGHT_USE_PSSM2) || defined(LIGHT_USE_PSSM3) || defined(LIGHT_USE_PSSM4) varying highp vec4 shadow_coord2; #endif -#if defined(LIGHT_USE_PSSM4) +#if defined(LIGHT_USE_PSSM3) || defined(LIGHT_USE_PSSM4) varying highp vec4 shadow_coord3; + +#if defined(LIGHT_USE_PSSM4) + varying highp vec4 shadow_coord4; +#endif #endif uniform vec4 light_clamp; @@ -2006,6 +2013,55 @@ FRAGMENT_SHADER_CODE #endif //LIGHT_USE_PSSM4 +#ifdef LIGHT_USE_PSSM3 + //take advantage of prefetch + float shadow1 = sample_shadow(light_directional_shadow, shadow_coord); + float shadow2 = sample_shadow(light_directional_shadow, shadow_coord2); + float shadow3 = sample_shadow(light_directional_shadow, shadow_coord3); + + if (depth_z < light_split_offsets.z) { + float pssm_fade = 0.0; + float shadow_att = 1.0; +#ifdef LIGHT_USE_PSSM_BLEND + float shadow_att2 = 1.0; + float pssm_blend = 0.0; + bool use_blend = true; +#endif + if (depth_z < light_split_offsets.y) { + if (depth_z < light_split_offsets.x) { + shadow_att = shadow1; + +#ifdef LIGHT_USE_PSSM_BLEND + shadow_att2 = shadow2; + + pssm_blend = smoothstep(0.0, light_split_offsets.x, depth_z); +#endif + } else { + shadow_att = shadow2; + +#ifdef LIGHT_USE_PSSM_BLEND + shadow_att2 = shadow3; + + pssm_blend = smoothstep(light_split_offsets.x, light_split_offsets.y, depth_z); +#endif + } + } else { + shadow_att = shadow3; + +#if defined(LIGHT_USE_PSSM_BLEND) + use_blend = false; +#endif + } +#if defined(LIGHT_USE_PSSM_BLEND) + if (use_blend) { + shadow_att = mix(shadow_att, shadow_att2, pssm_blend); + } +#endif + light_att *= mix(shadow_color.rgb, vec3(1.0), shadow_att); + } + +#endif //LIGHT_USE_PSSM3 + #ifdef LIGHT_USE_PSSM2 //take advantage of prefetch @@ -2046,7 +2102,7 @@ FRAGMENT_SHADER_CODE #endif //LIGHT_USE_PSSM2 -#if !defined(LIGHT_USE_PSSM4) && !defined(LIGHT_USE_PSSM2) +#if !defined(LIGHT_USE_PSSM4) && !defined(LIGHT_USE_PSSM3) && !defined(LIGHT_USE_PSSM2) light_att *= mix(shadow_color.rgb, vec3(1.0), sample_shadow(light_directional_shadow, shadow_coord)); #endif //orthogonal @@ -2056,6 +2112,8 @@ FRAGMENT_SHADER_CODE { #ifdef LIGHT_USE_PSSM4 if (depth_z < light_split_offsets.w) { +#elif defined(LIGHT_USE_PSSM3) + if (depth_z < light_split_offsets.z) { #elif defined(LIGHT_USE_PSSM2) if (depth_z < light_split_offsets.y) { #else @@ -2112,6 +2170,35 @@ FRAGMENT_SHADER_CODE #endif // LIGHT_USE_PSSM4 +#ifdef LIGHT_USE_PSSM3 + + if (depth_z < light_split_offsets.y) { + if (depth_z < light_split_offsets.x) { + pssm_coord = shadow_coord; + +#ifdef LIGHT_USE_PSSM_BLEND + pssm_coord2 = shadow_coord2; + pssm_blend = smoothstep(0.0, light_split_offsets.x, depth_z); +#endif + } else { + pssm_coord = shadow_coord2; + +#ifdef LIGHT_USE_PSSM_BLEND + pssm_coord2 = shadow_coord3; + pssm_blend = smoothstep(light_split_offsets.x, light_split_offsets.y, depth_z); +#endif + } + } else { + pssm_coord = shadow_coord3; + pssm_fade = smoothstep(light_split_offsets.y, light_split_offsets.z, depth_z); + +#if defined(LIGHT_USE_PSSM_BLEND) + use_blend = false; +#endif + } + +#endif // LIGHT_USE_PSSM3 + #ifdef LIGHT_USE_PSSM2 if (depth_z < light_split_offsets.x) { pssm_coord = shadow_coord; @@ -2130,7 +2217,7 @@ FRAGMENT_SHADER_CODE #endif // LIGHT_USE_PSSM2 -#if !defined(LIGHT_USE_PSSM4) && !defined(LIGHT_USE_PSSM2) +#if !defined(LIGHT_USE_PSSM4) && !defined(LIGHT_USE_PSSM3) && !defined(LIGHT_USE_PSSM2) { pssm_coord = shadow_coord; } diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 769e4eed502..32ee03ca950 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -463,6 +463,7 @@ int RasterizerSceneGLES3::get_directional_light_shadow_size(RID p_light_intance) case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: break; //none case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS: case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: shadow_size /= 2; break; @@ -2040,9 +2041,9 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL, false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW, false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4, false); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM3, false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2, false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND, false); - state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND, false); state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_5, false); state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_13, false); state.scene_shader.set_conditional(SceneShaderGLES3::USE_GI_PROBES, false); @@ -2067,6 +2068,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL, use_directional); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW, false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4, false); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM3, false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2, false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND, false); state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_5, shadow_filter_mode == SHADOW_FILTER_PCF5); @@ -2085,6 +2087,10 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2, true); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND, directional_light->light_ptr->directional_blend_splits); break; + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS: + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM3, true); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND, directional_light->light_ptr->directional_blend_splits); + break; case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4, true); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND, directional_light->light_ptr->directional_blend_splits); @@ -2227,6 +2233,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL, false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW, false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM4, false); + state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM3, false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM2, false); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND, false); state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS, false); @@ -2724,6 +2731,9 @@ void RasterizerSceneGLES3::_setup_directional_light(int p_index, const Transform case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: { shadow_count = 2; } break; + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS: { + shadow_count = 3; + } break; case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: { shadow_count = 4; } break; @@ -2735,7 +2745,7 @@ void RasterizerSceneGLES3::_setup_directional_light(int p_index, const Transform uint32_t width = li->directional_rect.size.x; uint32_t height = li->directional_rect.size.y; - if (li->light_ptr->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { + if (li->light_ptr->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS || li->light_ptr->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { width /= 2; height /= 2; @@ -4742,7 +4752,7 @@ void RasterizerSceneGLES3::render_shadow(RID p_light, RID p_shadow_atlas, int p_ width = light_instance->directional_rect.size.x; height = light_instance->directional_rect.size.y; - if (light->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { + if (light->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS || light->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { width /= 2; height /= 2; diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index b0134c8a258..a4d35a79b96 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -2129,11 +2129,15 @@ FRAGMENT_SHADER_CODE #ifdef LIGHT_USE_PSSM4 //ubershader-runtime value = shadow_split_offsets.w; #else //ubershader-runtime +#ifdef LIGHT_USE_PSSM3 //ubershader-runtime + value = shadow_split_offsets.z; +#else //ubershader-runtime #ifdef LIGHT_USE_PSSM2 //ubershader-runtime value = shadow_split_offsets.y; #else //ubershader-runtime value = shadow_split_offsets.x; #endif //ubershader-runtime +#endif //ubershader-runtime #endif //LIGHT_USE_PSSM4 //ubershader-runtime if (depth_z < value) { vec3 pssm_coord; @@ -2194,6 +2198,42 @@ FRAGMENT_SHADER_CODE #endif //LIGHT_USE_PSSM4 //ubershader-runtime +#ifdef LIGHT_USE_PSSM3 //ubershader-runtime + + if (depth_z < shadow_split_offsets.y) { + if (depth_z < shadow_split_offsets.x) { + highp vec4 splane = (shadow_matrix1 * vec4(vertex, 1.0)); + pssm_coord = splane.xyz / splane.w; + +#ifdef LIGHT_USE_PSSM_BLEND //ubershader-runtime + + splane = (shadow_matrix2 * vec4(vertex, 1.0)); + pssm_coord2 = splane.xyz / splane.w; + pssm_blend = smoothstep(0.0, shadow_split_offsets.x, depth_z); +#endif //ubershader-runtime + + } else { + highp vec4 splane = (shadow_matrix2 * vec4(vertex, 1.0)); + pssm_coord = splane.xyz / splane.w; + +#ifdef LIGHT_USE_PSSM_BLEND //ubershader-runtime + splane = (shadow_matrix3 * vec4(vertex, 1.0)); + pssm_coord2 = splane.xyz / splane.w; + pssm_blend = smoothstep(shadow_split_offsets.x, shadow_split_offsets.y, depth_z); +#endif //ubershader-runtime + } + } else { + highp vec4 splane = (shadow_matrix3 * vec4(vertex, 1.0)); + pssm_coord = splane.xyz / splane.w; + pssm_fade = smoothstep(shadow_split_offsets.y, shadow_split_offsets.z, depth_z); + +#ifdef LIGHT_USE_PSSM_BLEND //ubershader-runtime + use_blend = false; +#endif //ubershader-runtime + } + +#endif //LIGHT_USE_PSSM3 //ubershader-runtime + #ifdef LIGHT_USE_PSSM2 //ubershader-runtime if (depth_z < shadow_split_offsets.x) { @@ -2220,12 +2260,14 @@ FRAGMENT_SHADER_CODE #endif //LIGHT_USE_PSSM2 //ubershader-runtime #ifndef LIGHT_USE_PSSM2 //ubershader-runtime +#ifndef LIGHT_USE_PSSM3 //ubershader-runtime #ifndef LIGHT_USE_PSSM4 //ubershader-runtime { //regular orthogonal highp vec4 splane = (shadow_matrix1 * vec4(vertex, 1.0)); pssm_coord = splane.xyz / splane.w; } #endif //ubershader-runtime +#endif //ubershader-runtime #endif //ubershader-runtime //one one sample diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp index e9a9867f8ad..e0d21bca4e6 100644 --- a/scene/3d/light.cpp +++ b/scene/3d/light.cpp @@ -386,7 +386,7 @@ void DirectionalLight::_bind_methods() { ClassDB::bind_method(D_METHOD("is_blend_splits_enabled"), &DirectionalLight::is_blend_splits_enabled); ADD_GROUP("Directional Shadow", "directional_shadow_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "directional_shadow_mode", PROPERTY_HINT_ENUM, "Orthogonal (Fast),PSSM 2 Splits (Average),PSSM 4 Splits (Slow)"), "set_shadow_mode", "get_shadow_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "directional_shadow_mode", PROPERTY_HINT_ENUM, "Orthogonal (Fast),PSSM 2 Splits (Average),PSSM 3 Splits (Slow),PSSM 4 Splits (Very Slow)"), "set_shadow_mode", "get_shadow_mode"); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_split_1", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_1_OFFSET); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_split_2", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_2_OFFSET); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_split_3", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_3_OFFSET); @@ -398,6 +398,7 @@ void DirectionalLight::_bind_methods() { BIND_ENUM_CONSTANT(SHADOW_ORTHOGONAL); BIND_ENUM_CONSTANT(SHADOW_PARALLEL_2_SPLITS); + BIND_ENUM_CONSTANT(SHADOW_PARALLEL_3_SPLITS); BIND_ENUM_CONSTANT(SHADOW_PARALLEL_4_SPLITS); BIND_ENUM_CONSTANT(SHADOW_DEPTH_RANGE_STABLE); diff --git a/scene/3d/light.h b/scene/3d/light.h index 12288aa5a81..fbce9f678c0 100644 --- a/scene/3d/light.h +++ b/scene/3d/light.h @@ -139,6 +139,7 @@ public: enum ShadowMode { SHADOW_ORTHOGONAL, SHADOW_PARALLEL_2_SPLITS, + SHADOW_PARALLEL_3_SPLITS, SHADOW_PARALLEL_4_SPLITS }; diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp index 7ff8614ab1e..3bab10caff3 100644 --- a/servers/visual/visual_server_scene.cpp +++ b/servers/visual/visual_server_scene.cpp @@ -2514,6 +2514,9 @@ bool VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: splits = 2; break; + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS: + splits = 3; + break; case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: splits = 4; break; diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 9cd7ef3bc2c..733d18d34aa 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -2383,6 +2383,7 @@ void VisualServer::_bind_methods() { BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL); BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS); + BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS); BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS); BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE); BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED); diff --git a/servers/visual_server.h b/servers/visual_server.h index ba1e0534515..93a84bea0a6 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -494,6 +494,7 @@ public: enum LightDirectionalShadowMode { LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL, LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS, + LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS, LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS };