Merge pull request #70884 from clayjohn/Depth-prepass

Ignore depth draw optimization when using depth draw alpha prepass
This commit is contained in:
Rémi Verschelde 2023-01-03 23:23:29 +01:00
commit 0160fea1ce
No known key found for this signature in database
GPG key ID: C3336907360768E1
10 changed files with 22 additions and 21 deletions

View file

@ -529,13 +529,13 @@
The material will use the texture's alpha values for transparency.
</constant>
<constant name="TRANSPARENCY_ALPHA_SCISSOR" value="2" enum="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.
</constant>
<constant name="TRANSPARENCY_ALPHA_HASH" value="3" enum="Transparency">
The material will cut off all values below a spatially-deterministic threshold, the rest will remain opaque.
</constant>
<constant name="TRANSPARENCY_ALPHA_DEPTH_PRE_PASS" value="4" enum="Transparency">
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.
</constant>
<constant name="TRANSPARENCY_MAX" value="5" enum="Transparency">
Represents the size of the [enum Transparency] enum.

View file

@ -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::SceneMaterialData *>(GLES3::MaterialStorage::get_singleton()->material_get_data(scene_globals.default_material, RS::SHADER_SPATIAL));

View file

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

View file

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

View file

@ -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<SceneShaderForwardClustered::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D));

View file

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

View file

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

View file

@ -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<SceneShaderForwardMobile::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D));

View file

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

View file

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