From 062fb8b0dc53bfa1fffb293d6bee5bf7730ddf4c Mon Sep 17 00:00:00 2001 From: clayjohn Date: Tue, 3 Jan 2023 09:26:15 -0800 Subject: [PATCH] Ignore depth draw optimization when using depth draw alpha prepass This is necessary as the scene shader still uses alpha in this case so we can't discard fragments that weren't written to the depth buffer --- doc/classes/BaseMaterial3D.xml | 4 ++-- drivers/gles3/rasterizer_scene_gles3.cpp | 4 ++-- drivers/gles3/storage/material_storage.cpp | 6 +++--- drivers/gles3/storage/material_storage.h | 2 +- .../forward_clustered/render_forward_clustered.cpp | 4 ++-- .../forward_clustered/scene_shader_forward_clustered.cpp | 9 +++++---- .../forward_clustered/scene_shader_forward_clustered.h | 2 +- .../renderer_rd/forward_mobile/render_forward_mobile.cpp | 4 ++-- .../forward_mobile/scene_shader_forward_mobile.cpp | 6 +++--- .../forward_mobile/scene_shader_forward_mobile.h | 2 +- 10 files changed, 22 insertions(+), 21 deletions(-) diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml index 8a5048de6be..60225275f3d 100644 --- a/doc/classes/BaseMaterial3D.xml +++ b/doc/classes/BaseMaterial3D.xml @@ -529,13 +529,13 @@ The material will use the texture's alpha values for transparency. - The material will cut off all values below a threshold, the rest will remain opaque. The opaque portions will be rendering in the depth prepass. + The material will cut off all values below a threshold, the rest will remain opaque. The opaque portions will be rendered in the depth prepass. The material will cut off all values below a spatially-deterministic threshold, the rest will remain opaque. - The material will use the texture's alpha value for transparency, but will still be rendered in the depth prepass. + The material will use the texture's alpha value for transparency, but will discard fragments with an alpha of less than 0.99 during the depth prepass and fragments with an alpha less than 0.1 during the shadow pass. Represents the size of the [enum Transparency] enum. diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 1faecfd4d03..f0c60f6ed92 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -191,7 +191,7 @@ void RasterizerSceneGLES3::_geometry_instance_add_surface_with_material(Geometry if (has_alpha || has_read_screen_alpha || p_material->shader_data->depth_draw == GLES3::SceneShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == GLES3::SceneShaderData::DEPTH_TEST_DISABLED) { //material is only meant for alpha pass flags |= GeometryInstanceSurface::FLAG_PASS_ALPHA; - if (p_material->shader_data->uses_depth_pre_pass && !(p_material->shader_data->depth_draw == GLES3::SceneShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == GLES3::SceneShaderData::DEPTH_TEST_DISABLED)) { + if (p_material->shader_data->uses_depth_prepass_alpha && !(p_material->shader_data->depth_draw == GLES3::SceneShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == GLES3::SceneShaderData::DEPTH_TEST_DISABLED)) { flags |= GeometryInstanceSurface::FLAG_PASS_DEPTH; flags |= GeometryInstanceSurface::FLAG_PASS_SHADOW; } @@ -203,7 +203,7 @@ void RasterizerSceneGLES3::_geometry_instance_add_surface_with_material(Geometry GLES3::SceneMaterialData *material_shadow = nullptr; void *surface_shadow = nullptr; - if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip) { + if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_prepass_alpha && !p_material->shader_data->uses_alpha_clip) { flags |= GeometryInstanceSurface::FLAG_USES_SHARED_SHADOW_MATERIAL; material_shadow = static_cast(GLES3::MaterialStorage::get_singleton()->material_get_data(scene_globals.default_material, RS::SHADER_SPATIAL)); diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index ebafdc88d81..53ab3d23679 100644 --- a/drivers/gles3/storage/material_storage.cpp +++ b/drivers/gles3/storage/material_storage.cpp @@ -3237,7 +3237,7 @@ void SceneShaderData::set_code(const String &p_code) { uses_alpha = false; uses_alpha_clip = false; uses_blend_alpha = false; - uses_depth_pre_pass = false; + uses_depth_prepass_alpha = false; uses_discard = false; uses_roughness = false; uses_normal = false; @@ -3288,7 +3288,7 @@ void SceneShaderData::set_code(const String &p_code) { // Use alpha clip pipeline for alpha hash/dither. // This prevents sorting issues inherent to alpha blending and allows such materials to cast shadows. actions.usage_flag_pointers["ALPHA_HASH_SCALE"] = &uses_alpha_clip; - actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass; + actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_prepass_alpha; actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss; actions.usage_flag_pointers["SSS_TRANSMITTANCE_DEPTH"] = &uses_transmittance; @@ -3398,7 +3398,7 @@ bool SceneShaderData::casts_shadows() const { bool has_base_alpha = (uses_alpha && !uses_alpha_clip) || has_read_screen_alpha; bool has_alpha = has_base_alpha || uses_blend_alpha; - return !has_alpha || (uses_depth_pre_pass && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED)); + return !has_alpha || (uses_depth_prepass_alpha && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED)); } RS::ShaderNativeSourceCode SceneShaderData::get_native_source_code() const { diff --git a/drivers/gles3/storage/material_storage.h b/drivers/gles3/storage/material_storage.h index 9965d230702..32463d291b8 100644 --- a/drivers/gles3/storage/material_storage.h +++ b/drivers/gles3/storage/material_storage.h @@ -286,7 +286,7 @@ struct SceneShaderData : public ShaderData { bool uses_alpha; bool uses_blend_alpha; bool uses_alpha_clip; - bool uses_depth_pre_pass; + bool uses_depth_prepass_alpha; bool uses_discard; bool uses_roughness; bool uses_normal; 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 5b465fb45c6..bcee7315c8c 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -3465,7 +3465,7 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet if (has_alpha || has_read_screen_alpha || p_material->shader_data->depth_draw == SceneShaderForwardClustered::ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == SceneShaderForwardClustered::ShaderData::DEPTH_TEST_DISABLED) { //material is only meant for alpha pass flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA; - if (p_material->shader_data->uses_depth_pre_pass && !(p_material->shader_data->depth_draw == SceneShaderForwardClustered::ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == SceneShaderForwardClustered::ShaderData::DEPTH_TEST_DISABLED)) { + if (p_material->shader_data->uses_depth_prepass_alpha && !(p_material->shader_data->depth_draw == SceneShaderForwardClustered::ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == SceneShaderForwardClustered::ShaderData::DEPTH_TEST_DISABLED)) { flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH; flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW; } @@ -3481,7 +3481,7 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet SceneShaderForwardClustered::MaterialData *material_shadow = nullptr; void *surface_shadow = nullptr; - if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_position && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip && p_material->shader_data->cull_mode == SceneShaderForwardClustered::ShaderData::CULL_BACK && !p_material->shader_data->uses_point_size) { + if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_position && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_prepass_alpha && !p_material->shader_data->uses_alpha_clip && p_material->shader_data->cull_mode == SceneShaderForwardClustered::ShaderData::CULL_BACK && !p_material->shader_data->uses_point_size) { flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL; material_shadow = static_cast(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D)); 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 914ca258996..9074a23472d 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 @@ -61,7 +61,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { uses_alpha = false; uses_alpha_clip = false; uses_blend_alpha = false; - uses_depth_pre_pass = false; + uses_depth_prepass_alpha = false; uses_discard = false; uses_roughness = false; uses_normal = false; @@ -114,7 +114,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { // Use alpha clip pipeline for alpha hash/dither. // This prevents sorting issues inherent to alpha blending and allows such materials to cast shadows. actions.usage_flag_pointers["ALPHA_HASH_SCALE"] = &uses_alpha_clip; - actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass; + actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_prepass_alpha; actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss; actions.usage_flag_pointers["SSS_TRANSMITTANCE_DEPTH"] = &uses_transmittance; @@ -309,10 +309,11 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { } RD::PipelineDepthStencilState depth_stencil = depth_stencil_state; - if (depth_pre_pass_enabled && casts_shadows()) { + if (depth_pre_pass_enabled && casts_shadows() && !uses_depth_prepass_alpha) { // We already have a depth from the depth pre-pass, there is no need to write it again. // In addition we can use COMPARE_OP_EQUAL instead of COMPARE_OP_LESS_OR_EQUAL. // This way we can use the early depth test to discard transparent fragments before the fragment shader even starts. + // This cannot be used with depth_prepass_alpha as it uses a different threshold during the depth-prepass and regular drawing. depth_stencil.depth_compare_operator = RD::COMPARE_OP_EQUAL; depth_stencil.enable_depth_write = false; } @@ -394,7 +395,7 @@ bool SceneShaderForwardClustered::ShaderData::casts_shadows() const { bool has_base_alpha = (uses_alpha && !uses_alpha_clip) || has_read_screen_alpha; bool has_alpha = has_base_alpha || uses_blend_alpha; - return !has_alpha || (uses_depth_pre_pass && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED)); + return !has_alpha || (uses_depth_prepass_alpha && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED)); } RS::ShaderNativeSourceCode SceneShaderForwardClustered::ShaderData::get_native_source_code() const { 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 51e4dd44d5e..367f44f50cb 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 @@ -153,7 +153,7 @@ public: bool uses_alpha = false; bool uses_blend_alpha = false; bool uses_alpha_clip = false; - bool uses_depth_pre_pass = false; + bool uses_depth_prepass_alpha = false; bool uses_discard = false; bool uses_roughness = false; bool uses_normal = false; 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 53bcb1c0388..7904ea0527d 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -2378,7 +2378,7 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI if (has_alpha || has_read_screen_alpha || p_material->shader_data->depth_draw == SceneShaderForwardMobile::ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == SceneShaderForwardMobile::ShaderData::DEPTH_TEST_DISABLED) { //material is only meant for alpha pass flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA; - if (p_material->shader_data->uses_depth_pre_pass && !(p_material->shader_data->depth_draw == SceneShaderForwardMobile::ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == SceneShaderForwardMobile::ShaderData::DEPTH_TEST_DISABLED)) { + if (p_material->shader_data->uses_depth_prepass_alpha && !(p_material->shader_data->depth_draw == SceneShaderForwardMobile::ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == SceneShaderForwardMobile::ShaderData::DEPTH_TEST_DISABLED)) { flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH; flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW; } @@ -2394,7 +2394,7 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI SceneShaderForwardMobile::MaterialData *material_shadow = nullptr; void *surface_shadow = nullptr; - if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip) { + if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_prepass_alpha && !p_material->shader_data->uses_alpha_clip) { flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL; material_shadow = static_cast(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D)); 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 224bb341896..543b1e29f94 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 @@ -63,7 +63,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { uses_alpha = false; uses_alpha_clip = false; uses_blend_alpha = false; - uses_depth_pre_pass = false; + uses_depth_prepass_alpha = false; uses_discard = false; uses_roughness = false; uses_normal = false; @@ -115,7 +115,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { // Use alpha clip pipeline for alpha hash/dither. // This prevents sorting issues inherent to alpha blending and allows such materials to cast shadows. actions.usage_flag_pointers["ALPHA_HASH_SCALE"] = &uses_alpha_clip; - actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass; + actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_prepass_alpha; // actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss; // actions.usage_flag_pointers["SSS_TRANSMITTANCE_DEPTH"] = &uses_transmittance; @@ -341,7 +341,7 @@ bool SceneShaderForwardMobile::ShaderData::casts_shadows() const { bool has_base_alpha = (uses_alpha && !uses_alpha_clip) || has_read_screen_alpha; bool has_alpha = has_base_alpha || uses_blend_alpha; - return !has_alpha || (uses_depth_pre_pass && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED)); + return !has_alpha || (uses_depth_prepass_alpha && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED)); } RS::ShaderNativeSourceCode SceneShaderForwardMobile::ShaderData::get_native_source_code() const { 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 18a897a9e95..f90acf02478 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 @@ -114,7 +114,7 @@ public: bool uses_alpha = false; bool uses_blend_alpha = false; bool uses_alpha_clip = false; - bool uses_depth_pre_pass = false; + bool uses_depth_prepass_alpha = false; bool uses_discard = false; bool uses_roughness = false; bool uses_normal = false;