Skip to content

Commit

Permalink
Merge pull request godotengine#10 from Ansraer/ramatak_four_is_overkill
Browse files Browse the repository at this point in the history
Add support for 3 dir shadow splits
  • Loading branch information
hpvb committed Jul 3, 2023
2 parents 18cb448 + cfcbc31 commit e1ebb80
Show file tree
Hide file tree
Showing 11 changed files with 183 additions and 21 deletions.
7 changes: 5 additions & 2 deletions doc/classes/DirectionalLight.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<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).
</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].
</member>
<member name="directional_shadow_normal_bias" type="float" setter="set_param" getter="get_param" default="0.8">
Expand All @@ -48,7 +48,10 @@
<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.
</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.
</constant>
<constant name="SHADOW_DEPTH_RANGE_STABLE" value="0" enum="ShadowDepthRange">
Expand Down
5 changes: 4 additions & 1 deletion doc/classes/VisualServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3501,7 +3501,10 @@
<constant name="LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS" value="1" enum="LightDirectionalShadowMode">
Use 2 splits for shadow projection when using directional light.
</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.
</constant>
<constant name="LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE" value="0" enum="LightDirectionalShadowDepthRangeMode">
Expand Down
14 changes: 12 additions & 2 deletions drivers/gles2/rasterizer_scene_gles2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -1912,6 +1913,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);

Expand All @@ -1933,6 +1935,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;
Expand Down Expand Up @@ -2020,6 +2025,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;
Expand All @@ -2031,7 +2040,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;

Expand Down Expand Up @@ -2667,6 +2676,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);
Expand Down Expand Up @@ -3726,7 +3736,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;

Expand Down
111 changes: 99 additions & 12 deletions drivers/gles2/shaders/scene.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -2010,6 +2017,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
Expand Down Expand Up @@ -2050,7 +2106,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
Expand All @@ -2060,6 +2116,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
Expand Down Expand Up @@ -2116,6 +2174,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;
Expand All @@ -2134,7 +2221,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;
}
Expand Down
16 changes: 13 additions & 3 deletions drivers/gles3/rasterizer_scene_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -2037,9 +2038,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);
Expand All @@ -2064,6 +2065,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);
Expand All @@ -2082,6 +2084,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);
Expand Down Expand Up @@ -2224,6 +2230,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);
Expand Down Expand Up @@ -2721,6 +2728,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;
Expand All @@ -2732,7 +2742,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;

Expand Down Expand Up @@ -4756,7 +4766,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;

Expand Down
Loading

0 comments on commit e1ebb80

Please sign in to comment.