add support for 3 dir shadow splits

This commit is contained in:
Ansraer 2023-03-29 12:56:41 +02:00
parent b0c399ec8c
commit 54bc6a300e
11 changed files with 183 additions and 21 deletions

View File

@ -24,7 +24,7 @@
<member name="directional_shadow_max_distance" type="float" setter="set_param" getter="get_param" default="100.0"> <member name="directional_shadow_max_distance" type="float" setter="set_param" getter="get_param" default="100.0">
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 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).
</member> </member>
<member name="directional_shadow_mode" type="int" setter="set_shadow_mode" getter="get_shadow_mode" enum="DirectionalLight.ShadowMode" default="2"> <member name="directional_shadow_mode" type="int" setter="set_shadow_mode" getter="get_shadow_mode" enum="DirectionalLight.ShadowMode" default="3">
The light's shadow rendering algorithm. See [enum ShadowMode]. The light's shadow rendering algorithm. See [enum ShadowMode].
</member> </member>
<member name="directional_shadow_normal_bias" type="float" setter="set_param" getter="get_param" default="0.8"> <member name="directional_shadow_normal_bias" type="float" setter="set_param" getter="get_param" default="0.8">
@ -48,7 +48,10 @@
<constant name="SHADOW_PARALLEL_2_SPLITS" value="1" enum="ShadowMode"> <constant name="SHADOW_PARALLEL_2_SPLITS" value="1" enum="ShadowMode">
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 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.
</constant> </constant>
<constant name="SHADOW_PARALLEL_4_SPLITS" value="2" enum="ShadowMode"> <constant name="SHADOW_PARALLEL_3_SPLITS" value="2" enum="ShadowMode">
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.
</constant>
<constant name="SHADOW_PARALLEL_4_SPLITS" value="3" enum="ShadowMode">
Splits the view frustum in 4 areas, each with its own shadow map. This is the slowest directional shadow mode. Splits the view frustum in 4 areas, each with its own shadow map. This is the slowest directional shadow mode.
</constant> </constant>
<constant name="SHADOW_DEPTH_RANGE_STABLE" value="0" enum="ShadowDepthRange"> <constant name="SHADOW_DEPTH_RANGE_STABLE" value="0" enum="ShadowDepthRange">

View File

@ -3581,7 +3581,10 @@
<constant name="LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS" value="1" enum="LightDirectionalShadowMode"> <constant name="LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS" value="1" enum="LightDirectionalShadowMode">
Use 2 splits for shadow projection when using directional light. Use 2 splits for shadow projection when using directional light.
</constant> </constant>
<constant name="LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS" value="2" enum="LightDirectionalShadowMode"> <constant name="LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS" value="2" enum="LightDirectionalShadowMode">
Use 3 splits for shadow projection when using directional light.
</constant>
<constant name="LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS" value="3" enum="LightDirectionalShadowMode">
Use 4 splits for shadow projection when using directional light. Use 4 splits for shadow projection when using directional light.
</constant> </constant>
<constant name="LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE" value="0" enum="LightDirectionalShadowDepthRangeMode"> <constant name="LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE" value="0" enum="LightDirectionalShadowDepthRangeMode">

View File

@ -514,6 +514,7 @@ int RasterizerSceneGLES2::get_directional_light_shadow_size(RID p_light_intance)
case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:
break; //none break; //none
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS:
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS:
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS:
shadow_size /= 2; shadow_size /= 2;
break; 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_OMNI, false);
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_SPOT, 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_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_PSSM4, false);
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, 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); state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, true);
} break; } 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: { case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: {
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, true); state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, true);
} break; } break;
@ -2023,6 +2028,10 @@ void RasterizerSceneGLES2::_setup_light(LightInstance *light, ShadowAtlas *shado
shadow_count = 2; shadow_count = 2;
} break; } break;
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS: {
shadow_count = 3;
} break;
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: { case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: {
shadow_count = 4; shadow_count = 4;
} break; } break;
@ -2034,7 +2043,7 @@ void RasterizerSceneGLES2::_setup_light(LightInstance *light, ShadowAtlas *shado
uint32_t width = light->directional_rect.size.x; uint32_t width = light->directional_rect.size.x;
uint32_t height = light->directional_rect.size.y; 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; width /= 2;
height /= 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_INSTANCING, false);
state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, 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_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_PSSM2, false);
state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, false); state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, false);
state.scene_shader.set_conditional(SceneShaderGLES2::USE_VERTEX_LIGHTING, 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; width = light_instance->directional_rect.size.width;
height = light_instance->directional_rect.size.height; 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; width /= 2;
height /= 2; height /= 2;

View File

@ -166,18 +166,19 @@ uniform highp float shadow_dual_paraboloid_render_side;
uniform highp mat4 light_shadow_matrix; uniform highp mat4 light_shadow_matrix;
varying highp vec4 shadow_coord; 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; uniform highp mat4 light_shadow_matrix2;
varying highp vec4 shadow_coord2; varying highp vec4 shadow_coord2;
#endif #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_matrix3;
uniform highp mat4 light_shadow_matrix4;
varying highp vec4 shadow_coord3; 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
#endif #endif
@ -625,14 +626,16 @@ VERTEX_SHADER_CODE
vec4 vi4 = vec4(vertex_interp, 1.0); vec4 vi4 = vec4(vertex_interp, 1.0);
shadow_coord = light_shadow_matrix * vi4; 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; shadow_coord2 = light_shadow_matrix2 * vi4;
#endif #endif
#if defined(LIGHT_USE_PSSM4) #if defined(LIGHT_USE_PSSM3) || defined(LIGHT_USE_PSSM4)
shadow_coord3 = light_shadow_matrix3 * vi4; 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
#endif //use shadow and use lighting #endif //use shadow and use lighting
@ -1078,15 +1081,19 @@ uniform highp vec4 light_split_offsets;
varying highp vec4 shadow_coord; 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; varying highp vec4 shadow_coord2;
#endif #endif
#if defined(LIGHT_USE_PSSM4) #if defined(LIGHT_USE_PSSM3) || defined(LIGHT_USE_PSSM4)
varying highp vec4 shadow_coord3; varying highp vec4 shadow_coord3;
#if defined(LIGHT_USE_PSSM4)
varying highp vec4 shadow_coord4; varying highp vec4 shadow_coord4;
#endif
#endif #endif
uniform vec4 light_clamp; uniform vec4 light_clamp;
@ -2006,6 +2013,55 @@ FRAGMENT_SHADER_CODE
#endif //LIGHT_USE_PSSM4 #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 #ifdef LIGHT_USE_PSSM2
//take advantage of prefetch //take advantage of prefetch
@ -2046,7 +2102,7 @@ FRAGMENT_SHADER_CODE
#endif //LIGHT_USE_PSSM2 #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)); light_att *= mix(shadow_color.rgb, vec3(1.0), sample_shadow(light_directional_shadow, shadow_coord));
#endif //orthogonal #endif //orthogonal
@ -2056,6 +2112,8 @@ FRAGMENT_SHADER_CODE
{ {
#ifdef LIGHT_USE_PSSM4 #ifdef LIGHT_USE_PSSM4
if (depth_z < light_split_offsets.w) { if (depth_z < light_split_offsets.w) {
#elif defined(LIGHT_USE_PSSM3)
if (depth_z < light_split_offsets.z) {
#elif defined(LIGHT_USE_PSSM2) #elif defined(LIGHT_USE_PSSM2)
if (depth_z < light_split_offsets.y) { if (depth_z < light_split_offsets.y) {
#else #else
@ -2112,6 +2170,35 @@ FRAGMENT_SHADER_CODE
#endif // LIGHT_USE_PSSM4 #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 #ifdef LIGHT_USE_PSSM2
if (depth_z < light_split_offsets.x) { if (depth_z < light_split_offsets.x) {
pssm_coord = shadow_coord; pssm_coord = shadow_coord;
@ -2130,7 +2217,7 @@ FRAGMENT_SHADER_CODE
#endif // LIGHT_USE_PSSM2 #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; pssm_coord = shadow_coord;
} }

View File

@ -463,6 +463,7 @@ int RasterizerSceneGLES3::get_directional_light_shadow_size(RID p_light_intance)
case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:
break; //none break; //none
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS:
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS:
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS:
shadow_size /= 2; shadow_size /= 2;
break; 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::USE_LIGHT_DIRECTIONAL, false);
state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW, 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_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_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::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_5, false);
state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_13, false); state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_13, false);
state.scene_shader.set_conditional(SceneShaderGLES3::USE_GI_PROBES, 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::USE_LIGHT_DIRECTIONAL, use_directional);
state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW, 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_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_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, shadow_filter_mode == SHADOW_FILTER_PCF5); 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_PSSM2, true);
state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND, directional_light->light_ptr->directional_blend_splits); state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND, directional_light->light_ptr->directional_blend_splits);
break; 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: 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_PSSM4, true);
state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND, directional_light->light_ptr->directional_blend_splits); 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::USE_LIGHT_DIRECTIONAL, false);
state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_DIRECTIONAL_SHADOW, 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_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_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::SHADELESS, 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: { case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: {
shadow_count = 2; shadow_count = 2;
} break; } break;
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS: {
shadow_count = 3;
} break;
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: { case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: {
shadow_count = 4; shadow_count = 4;
} break; } 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 width = li->directional_rect.size.x;
uint32_t height = li->directional_rect.size.y; 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; width /= 2;
height /= 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; width = light_instance->directional_rect.size.x;
height = light_instance->directional_rect.size.y; 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; width /= 2;
height /= 2; height /= 2;

View File

@ -2129,11 +2129,15 @@ FRAGMENT_SHADER_CODE
#ifdef LIGHT_USE_PSSM4 //ubershader-runtime #ifdef LIGHT_USE_PSSM4 //ubershader-runtime
value = shadow_split_offsets.w; value = shadow_split_offsets.w;
#else //ubershader-runtime #else //ubershader-runtime
#ifdef LIGHT_USE_PSSM3 //ubershader-runtime
value = shadow_split_offsets.z;
#else //ubershader-runtime
#ifdef LIGHT_USE_PSSM2 //ubershader-runtime #ifdef LIGHT_USE_PSSM2 //ubershader-runtime
value = shadow_split_offsets.y; value = shadow_split_offsets.y;
#else //ubershader-runtime #else //ubershader-runtime
value = shadow_split_offsets.x; value = shadow_split_offsets.x;
#endif //ubershader-runtime #endif //ubershader-runtime
#endif //ubershader-runtime
#endif //LIGHT_USE_PSSM4 //ubershader-runtime #endif //LIGHT_USE_PSSM4 //ubershader-runtime
if (depth_z < value) { if (depth_z < value) {
vec3 pssm_coord; vec3 pssm_coord;
@ -2194,6 +2198,42 @@ FRAGMENT_SHADER_CODE
#endif //LIGHT_USE_PSSM4 //ubershader-runtime #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 #ifdef LIGHT_USE_PSSM2 //ubershader-runtime
if (depth_z < shadow_split_offsets.x) { if (depth_z < shadow_split_offsets.x) {
@ -2220,12 +2260,14 @@ FRAGMENT_SHADER_CODE
#endif //LIGHT_USE_PSSM2 //ubershader-runtime #endif //LIGHT_USE_PSSM2 //ubershader-runtime
#ifndef LIGHT_USE_PSSM2 //ubershader-runtime #ifndef LIGHT_USE_PSSM2 //ubershader-runtime
#ifndef LIGHT_USE_PSSM3 //ubershader-runtime
#ifndef LIGHT_USE_PSSM4 //ubershader-runtime #ifndef LIGHT_USE_PSSM4 //ubershader-runtime
{ //regular orthogonal { //regular orthogonal
highp vec4 splane = (shadow_matrix1 * vec4(vertex, 1.0)); highp vec4 splane = (shadow_matrix1 * vec4(vertex, 1.0));
pssm_coord = splane.xyz / splane.w; pssm_coord = splane.xyz / splane.w;
} }
#endif //ubershader-runtime #endif //ubershader-runtime
#endif //ubershader-runtime
#endif //ubershader-runtime #endif //ubershader-runtime
//one one sample //one one sample

View File

@ -386,7 +386,7 @@ void DirectionalLight::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_blend_splits_enabled"), &DirectionalLight::is_blend_splits_enabled); ClassDB::bind_method(D_METHOD("is_blend_splits_enabled"), &DirectionalLight::is_blend_splits_enabled);
ADD_GROUP("Directional Shadow", "directional_shadow_"); 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_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_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); 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_ORTHOGONAL);
BIND_ENUM_CONSTANT(SHADOW_PARALLEL_2_SPLITS); 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_PARALLEL_4_SPLITS);
BIND_ENUM_CONSTANT(SHADOW_DEPTH_RANGE_STABLE); BIND_ENUM_CONSTANT(SHADOW_DEPTH_RANGE_STABLE);

View File

@ -139,6 +139,7 @@ public:
enum ShadowMode { enum ShadowMode {
SHADOW_ORTHOGONAL, SHADOW_ORTHOGONAL,
SHADOW_PARALLEL_2_SPLITS, SHADOW_PARALLEL_2_SPLITS,
SHADOW_PARALLEL_3_SPLITS,
SHADOW_PARALLEL_4_SPLITS SHADOW_PARALLEL_4_SPLITS
}; };

View File

@ -2514,6 +2514,9 @@ bool VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS:
splits = 2; splits = 2;
break; break;
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS:
splits = 3;
break;
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS:
splits = 4; splits = 4;
break; break;

View File

@ -2383,6 +2383,7 @@ void VisualServer::_bind_methods() {
BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL); BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL);
BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS); 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_PARALLEL_4_SPLITS);
BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE); BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE);
BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED); BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED);

View File

@ -494,6 +494,7 @@ public:
enum LightDirectionalShadowMode { enum LightDirectionalShadowMode {
LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL, LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL,
LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS, LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS,
LIGHT_DIRECTIONAL_SHADOW_PARALLEL_3_SPLITS,
LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS
}; };