From ca23d06a3140ef2f90d25529414137072e05aace Mon Sep 17 00:00:00 2001 From: clayjohn Date: Fri, 28 Apr 2023 16:02:10 -0700 Subject: [PATCH] Re-implement the PSSM_SPLITS debug option This uses a render_mode instead of shadow_color to avoid adding a cost to the basic shader --- .../render_forward_clustered.cpp | 3 +++ .../scene_shader_forward_clustered.cpp | 26 ++++++++++++++++++ .../scene_shader_forward_clustered.h | 5 ++++ .../forward_mobile/render_forward_mobile.cpp | 3 +++ .../scene_shader_forward_mobile.cpp | 27 +++++++++++++++++++ .../scene_shader_forward_mobile.h | 5 ++++ .../scene_forward_clustered.glsl | 23 +++++++++++++++- .../forward_mobile/scene_forward_mobile.glsl | 23 +++++++++++++++- .../renderer_rd/storage_rd/light_storage.cpp | 4 --- servers/rendering/shader_types.cpp | 1 + 10 files changed, 114 insertions(+), 6 deletions(-) diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index c7d85a3bbf23..779249c2da58 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -334,6 +334,9 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p } else if (unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW)) { material_uniform_set = scene_shader.overdraw_material_uniform_set; shader = scene_shader.overdraw_material_shader_ptr; + } else if (unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_PSSM_SPLITS)) { + material_uniform_set = scene_shader.debug_shadow_splits_material_uniform_set; + shader = scene_shader.debug_shadow_splits_material_shader_ptr; } else { #endif material_uniform_set = surf->material_uniform_set; diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index 6c948d3474e8..35d1071ab6c8 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -465,9 +465,11 @@ SceneShaderForwardClustered::~SceneShaderForwardClustered() { material_storage->shader_free(overdraw_material_shader); material_storage->shader_free(default_shader); + material_storage->shader_free(debug_shadow_splits_material_shader); material_storage->material_free(overdraw_material); material_storage->material_free(default_material); + material_storage->material_free(debug_shadow_splits_material); } void SceneShaderForwardClustered::init(const String p_defines) { @@ -719,6 +721,7 @@ void SceneShaderForwardClustered::init(const String p_defines) { actions.render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n"; actions.render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n"; actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n"; + actions.render_mode_defines["debug_shadow_splits"] = "#define DEBUG_DRAW_PSSM_SPLITS\n"; actions.sampler_array_name = "material_samplers"; actions.base_texture_binding_index = 1; @@ -792,6 +795,29 @@ void fragment() { overdraw_material_uniform_set = md->uniform_set; } + { + debug_shadow_splits_material_shader = material_storage->shader_allocate(); + material_storage->shader_initialize(debug_shadow_splits_material_shader); + material_storage->shader_set_code(debug_shadow_splits_material_shader, R"( +// 3D debug shadow splits mode shader(mobile). + +shader_type spatial; + +render_mode debug_shadow_splits; + +void fragment() { + ALBEDO = vec3(1.0, 1.0, 1.0); +} +)"); + debug_shadow_splits_material = material_storage->material_allocate(); + material_storage->material_initialize(debug_shadow_splits_material); + material_storage->material_set_shader(debug_shadow_splits_material, debug_shadow_splits_material_shader); + + MaterialData *md = static_cast(material_storage->material_get_data(debug_shadow_splits_material, RendererRD::MaterialStorage::SHADER_TYPE_3D)); + debug_shadow_splits_material_shader_ptr = md->shader_data; + debug_shadow_splits_material_uniform_set = md->uniform_set; + } + { default_vec4_xform_buffer = RD::get_singleton()->storage_buffer_create(256); Vector uniforms; diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h index ffaf091b36f5..bdafc4c27ea2 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h @@ -222,6 +222,8 @@ class SceneShaderForwardClustered { RID default_material; RID overdraw_material_shader; RID overdraw_material; + RID debug_shadow_splits_material_shader; + RID debug_shadow_splits_material; RID default_shader_rd; RID default_shader_sdfgi_rd; @@ -236,6 +238,9 @@ class SceneShaderForwardClustered { RID overdraw_material_uniform_set; ShaderData *overdraw_material_shader_ptr = nullptr; + RID debug_shadow_splits_material_uniform_set; + ShaderData *debug_shadow_splits_material_shader_ptr = nullptr; + Vector default_specialization_constants; HashSet valid_color_pass_pipelines; SceneShaderForwardClustered(); diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index b9edc46aeee9..0b4157c5d63d 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -2113,6 +2113,9 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr } else if (unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW)) { material_uniform_set = scene_shader.overdraw_material_uniform_set; shader = scene_shader.overdraw_material_shader_ptr; + } else if (unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_PSSM_SPLITS)) { + material_uniform_set = scene_shader.debug_shadow_splits_material_uniform_set; + shader = scene_shader.debug_shadow_splits_material_shader_ptr; } else { #endif material_uniform_set = surf->material_uniform_set; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index a93b99446702..101ae189480b 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -608,6 +608,7 @@ void SceneShaderForwardMobile::init(const String p_defines) { actions.render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n"; actions.render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n"; actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n"; + actions.render_mode_defines["debug_shadow_splits"] = "#define DEBUG_DRAW_PSSM_SPLITS\n"; actions.sampler_array_name = "material_samplers"; actions.base_texture_binding_index = 1; @@ -681,6 +682,30 @@ void fragment() { overdraw_material_uniform_set = md->uniform_set; } + { + debug_shadow_splits_material_shader = material_storage->shader_allocate(); + material_storage->shader_initialize(debug_shadow_splits_material_shader); + // Use relatively low opacity so that more "layers" of overlapping objects can be distinguished. + material_storage->shader_set_code(debug_shadow_splits_material_shader, R"( +// 3D debug shadow splits mode shader(mobile). + +shader_type spatial; + +render_mode debug_shadow_splits. + +void fragment() { + ALBEDO = vec3(1.0, 1.0, 1.0); +} +)"); + debug_shadow_splits_material = material_storage->material_allocate(); + material_storage->material_initialize(debug_shadow_splits_material); + material_storage->material_set_shader(debug_shadow_splits_material, debug_shadow_splits_material_shader); + + MaterialData *md = static_cast(material_storage->material_get_data(debug_shadow_splits_material, RendererRD::MaterialStorage::SHADER_TYPE_3D)); + debug_shadow_splits_material_shader_ptr = md->shader_data; + debug_shadow_splits_material_uniform_set = md->uniform_set; + } + { default_vec4_xform_buffer = RD::get_singleton()->storage_buffer_create(256); Vector uniforms; @@ -723,7 +748,9 @@ SceneShaderForwardMobile::~SceneShaderForwardMobile() { material_storage->shader_free(overdraw_material_shader); material_storage->shader_free(default_shader); + material_storage->shader_free(debug_shadow_splits_material_shader); material_storage->material_free(overdraw_material); material_storage->material_free(default_material); + material_storage->material_free(debug_shadow_splits_material); } diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h index 6f1f00cedc74..0b98746d06aa 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h @@ -181,6 +181,8 @@ class SceneShaderForwardMobile { RID default_material; RID overdraw_material_shader; RID overdraw_material; + RID debug_shadow_splits_material_shader; + RID debug_shadow_splits_material; RID default_shader_rd; RID default_vec4_xform_buffer; @@ -194,6 +196,9 @@ class SceneShaderForwardMobile { RID overdraw_material_uniform_set; ShaderData *overdraw_material_shader_ptr = nullptr; + RID debug_shadow_splits_material_uniform_set; + ShaderData *debug_shadow_splits_material_shader_ptr = nullptr; + SceneShaderForwardMobile(); ~SceneShaderForwardMobile(); diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl index 97501707240d..cec54a2c5f93 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl @@ -1817,9 +1817,30 @@ void fragment_shader(in SceneData scene_data) { blur_shadow(shadow); +#ifdef DEBUG_DRAW_PSSM_SPLITS + vec3 tint = vec3(1.0); + if (-vertex.z < directional_lights.data[i].shadow_split_offsets.x) { + tint = vec3(1.0, 0.0, 0.0); + } else if (-vertex.z < directional_lights.data[i].shadow_split_offsets.y) { + tint = vec3(0.0, 1.0, 0.0); + } else if (-vertex.z < directional_lights.data[i].shadow_split_offsets.z) { + tint = vec3(0.0, 0.0, 1.0); + } else { + tint = vec3(1.0, 1.0, 0.0); + } + tint = mix(tint, vec3(1.0), shadow); + shadow = 1.0; +#endif + float size_A = sc_use_light_soft_shadows ? directional_lights.data[i].size : 0.0; - light_compute(normal, directional_lights.data[i].direction, normalize(view), size_A, directional_lights.data[i].color * directional_lights.data[i].energy, true, shadow, f0, orms, 1.0, albedo, alpha, + light_compute(normal, directional_lights.data[i].direction, normalize(view), size_A, +#ifndef DEBUG_DRAW_PSSM_SPLITS + directional_lights.data[i].color * directional_lights.data[i].energy, +#else + directional_lights.data[i].color * directional_lights.data[i].energy * tint, +#endif + true, shadow, f0, orms, 1.0, albedo, alpha, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl index f87fa8d2ab57..bb9216c4fa0d 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl @@ -1534,7 +1534,28 @@ void main() { #endif blur_shadow(shadow); - light_compute(normal, directional_lights.data[i].direction, normalize(view), 0.0, directional_lights.data[i].color * directional_lights.data[i].energy, true, shadow, f0, orms, 1.0, albedo, alpha, +#ifdef DEBUG_DRAW_PSSM_SPLITS + vec3 tint = vec3(1.0); + if (-vertex.z < directional_lights.data[i].shadow_split_offsets.x) { + tint = vec3(1.0, 0.0, 0.0); + } else if (-vertex.z < directional_lights.data[i].shadow_split_offsets.y) { + tint = vec3(0.0, 1.0, 0.0); + } else if (-vertex.z < directional_lights.data[i].shadow_split_offsets.z) { + tint = vec3(0.0, 0.0, 1.0); + } else { + tint = vec3(1.0, 1.0, 0.0); + } + tint = mix(tint, vec3(1.0), shadow); + shadow = 1.0; +#endif + + light_compute(normal, directional_lights.data[i].direction, normalize(view), 0.0, +#ifndef DEBUG_DRAW_PSSM_SPLITS + directional_lights.data[i].color * directional_lights.data[i].energy, +#else + directional_lights.data[i].color * directional_lights.data[i].energy * tint, +#endif + true, shadow, f0, orms, 1.0, albedo, alpha, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp index e65d842a677a..a5ec62b546df 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp @@ -634,10 +634,6 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged light_data.size = 1.0 - Math::cos(Math::deg_to_rad(size)); //angle to cosine offset - if (RendererSceneRenderRD::get_singleton()->get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_PSSM_SPLITS) { - WARN_PRINT_ONCE("The DirectionalLight3D PSSM splits debug draw mode is not reimplemented yet."); - } - light_data.shadow_opacity = (p_using_shadows && light->shadow) ? light->param[RS::LIGHT_PARAM_SHADOW_OPACITY] : 0.0; diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index d95caeddc532..6bb93ef308fe 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -225,6 +225,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("particle_trails") }); shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("alpha_to_coverage") }); shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("alpha_to_coverage_and_one") }); + shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("debug_shadow_splits") }); } /************ CANVAS ITEM **************************/