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
This commit is contained in:
clayjohn 2023-04-28 16:02:10 -07:00
parent 9f12e7b52d
commit ca23d06a31
10 changed files with 114 additions and 6 deletions

View file

@ -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;

View file

@ -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<MaterialData *>(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<RD::Uniform> uniforms;

View file

@ -222,6 +222,8 @@ public:
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 @@ public:
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<RD::PipelineSpecializationConstant> default_specialization_constants;
HashSet<uint32_t> valid_color_pass_pipelines;
SceneShaderForwardClustered();

View file

@ -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;

View file

@ -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<MaterialData *>(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<RD::Uniform> 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);
}

View file

@ -181,6 +181,8 @@ public:
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 @@ public:
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();

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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 **************************/