diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml index fc8af02869eb..2a7383682fe4 100644 --- a/doc/classes/BaseMaterial3D.xml +++ b/doc/classes/BaseMaterial3D.xml @@ -151,6 +151,10 @@ Determines when depth rendering takes place. See [enum DepthDrawMode]. See also [member transparency]. + + Determines which comparison operator is used when testing depth. See [enum DepthFunction]. + [b]Note:[/b] Changing [member depth_function] to a non-default value only has a visible effect when used on a transparent material, or a material that has [member depth_draw_mode] set to [constant DEPTH_DRAW_DISABLED]. + Texture that specifies the color of the detail overlay. [member detail_albedo]'s alpha channel is used as a mask, even when the material is opaque. To use a dedicated texture as a mask, see [member detail_mask]. [b]Note:[/b] [member detail_albedo] is [i]not[/i] modulated by [member albedo_color]. @@ -631,6 +635,30 @@ Objects will not write their depth to the depth buffer, even during the depth prepass (if enabled). + + Depth check succeeds if less than or equal to existing depth. + + + Depth check succeeds if less than existing depth. + + + Depth check succeeds if equal to existing depth. + + + Depth check succeeds if greater than existing depth. + + + Depth check succeeds if not equal to existing depth. + + + Default depth function. Depth check succeeds if greater than or equal to existing depth. + + + Depth check always succeeds. + + + Depth check never succeeds. + Default cull mode. The back of the object is culled when not visible. Back face triangles will be culled when facing the camera. This results in only the front side of triangles being drawn. For closed-surface meshes, this means that only the exterior of the mesh will be visible. diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index a6796a1a6bbb..53c334534067 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -2190,7 +2190,7 @@ void RasterizerSceneGLES3::_render_shadow_pass(RID p_light, RID p_shadow_atlas, scene_state.reset_gl_state(); scene_state.enable_gl_depth_test(true); scene_state.enable_gl_depth_draw(true); - glDepthFunc(GL_GREATER); + scene_state.set_gl_depth_func(GLES3::SceneShaderData::DEPTH_FUNCTION_GREATER); glColorMask(0, 0, 0, 0); glDrawBuffers(0, nullptr); @@ -2493,7 +2493,7 @@ void RasterizerSceneGLES3::render_scene(const Ref &p_render_ scene_state.enable_gl_depth_test(true); scene_state.enable_gl_depth_draw(true); scene_state.enable_gl_blend(false); - glDepthFunc(GL_GEQUAL); + scene_state.set_gl_depth_func(GLES3::SceneShaderData::DEPTH_FUNCTION_GREATER_OR_EQUAL); scene_state.enable_gl_scissor_test(false); glColorMask(0, 0, 0, 0); @@ -2531,7 +2531,7 @@ void RasterizerSceneGLES3::render_scene(const Ref &p_render_ scene_state.enable_gl_scissor_test(false); scene_state.enable_gl_depth_test(true); scene_state.enable_gl_depth_draw(true); - glDepthFunc(GL_GEQUAL); + scene_state.set_gl_depth_func(GLES3::SceneShaderData::DEPTH_FUNCTION_GREATER_OR_EQUAL); { GLuint db = GL_COLOR_ATTACHMENT0; @@ -2591,6 +2591,7 @@ void RasterizerSceneGLES3::render_scene(const Ref &p_render_ RENDER_TIMESTAMP("Render Sky"); scene_state.enable_gl_depth_test(true); + scene_state.set_gl_depth_func(GLES3::SceneShaderData::DEPTH_FUNCTION_GREATER_OR_EQUAL); scene_state.enable_gl_blend(false); scene_state.set_gl_cull_mode(GLES3::SceneShaderData::CULL_BACK); @@ -2971,6 +2972,8 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params, scene_state.enable_gl_depth_test(shader->depth_test == GLES3::SceneShaderData::DEPTH_TEST_ENABLED); } + scene_state.set_gl_depth_func(shader->depth_function); + if constexpr (p_pass_mode != PASS_MODE_SHADOW) { if (shader->depth_draw == GLES3::SceneShaderData::DEPTH_DRAW_OPAQUE) { scene_state.enable_gl_depth_draw((p_pass_mode == PASS_MODE_COLOR && !GLES3::Config::get_singleton()->use_depth_prepass) || p_pass_mode == PASS_MODE_DEPTH); @@ -3606,7 +3609,7 @@ void RasterizerSceneGLES3::render_particle_collider_heightfield(RID p_collider, scene_state.reset_gl_state(); scene_state.enable_gl_depth_test(true); scene_state.enable_gl_depth_draw(true); - glDepthFunc(GL_GREATER); + scene_state.set_gl_depth_func(GLES3::SceneShaderData::DEPTH_FUNCTION_GREATER); glDrawBuffers(0, nullptr); @@ -3652,7 +3655,7 @@ void RasterizerSceneGLES3::_render_uv2(const PagedArray draw_buffers; draw_buffers.push_back(GL_COLOR_ATTACHMENT0); @@ -3745,7 +3748,7 @@ void RasterizerSceneGLES3::_render_buffers_debug_draw(Ref(&depth_testi, DEPTH_TEST_DISABLED); + actions.render_mode_values["depth_function_less_or_equal"] = Pair(&depth_functioni, DEPTH_FUNCTION_LESS_OR_EQUAL); + actions.render_mode_values["depth_function_less"] = Pair(&depth_functioni, DEPTH_FUNCTION_LESS); + actions.render_mode_values["depth_function_equal"] = Pair(&depth_functioni, DEPTH_FUNCTION_EQUAL); + actions.render_mode_values["depth_function_greater"] = Pair(&depth_functioni, DEPTH_FUNCTION_GREATER); + actions.render_mode_values["depth_function_not_equal"] = Pair(&depth_functioni, DEPTH_FUNCTION_NOT_EQUAL); + actions.render_mode_values["depth_function_greater_or_equal"] = Pair(&depth_functioni, DEPTH_FUNCTION_GREATER_OR_EQUAL); + actions.render_mode_values["depth_function_always"] = Pair(&depth_functioni, DEPTH_FUNCTION_ALWAYS); + actions.render_mode_values["depth_function_never"] = Pair(&depth_functioni, DEPTH_FUNCTION_NEVER); + actions.render_mode_values["cull_disabled"] = Pair(&cull_modei, CULL_DISABLED); actions.render_mode_values["cull_front"] = Pair(&cull_modei, CULL_FRONT); actions.render_mode_values["cull_back"] = Pair(&cull_modei, CULL_BACK); @@ -2978,6 +2988,7 @@ void SceneShaderData::set_code(const String &p_code) { alpha_antialiasing_mode = AlphaAntiAliasing(alpha_antialiasing_modei); depth_draw = DepthDraw(depth_drawi); depth_test = DepthTest(depth_testi); + depth_function = DepthFunction(depth_functioni); cull_mode = Cull(cull_modei); vertex_input_mask = RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL; // We can always read vertices and normals. diff --git a/drivers/gles3/storage/material_storage.h b/drivers/gles3/storage/material_storage.h index 392ebcc570d9..28a2f5331689 100644 --- a/drivers/gles3/storage/material_storage.h +++ b/drivers/gles3/storage/material_storage.h @@ -263,6 +263,18 @@ struct SceneShaderData : public ShaderData { DEPTH_TEST_ENABLED }; + enum DepthFunction { + DEPTH_FUNCTION_LESS_OR_EQUAL, + DEPTH_FUNCTION_LESS, + DEPTH_FUNCTION_EQUAL, + DEPTH_FUNCTION_GREATER, + DEPTH_FUNCTION_NOT_EQUAL, + DEPTH_FUNCTION_GREATER_OR_EQUAL, + DEPTH_FUNCTION_ALWAYS, + DEPTH_FUNCTION_NEVER, + DEPTH_FUNCTION_MAX + }; + enum Cull { CULL_DISABLED, CULL_FRONT, @@ -292,6 +304,7 @@ struct SceneShaderData : public ShaderData { AlphaAntiAliasing alpha_antialiasing_mode; DepthDraw depth_draw; DepthTest depth_test; + DepthFunction depth_function; Cull cull_mode; bool uses_point_size; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 7d121c9d87fb..ea121003b69b 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -727,6 +727,35 @@ void BaseMaterial3D::_update_shader() { break; // Internal value, skip. } + switch (depth_function) { + case DEPTH_FUNCTION_LESS_OR_EQUAL: + code += ",depth_function_less_or_equal"; + break; + case DEPTH_FUNCTION_LESS: + code += ",depth_function_less"; + break; + case DEPTH_FUNCTION_EQUAL: + code += ",depth_function_equal"; + break; + case DEPTH_FUNCTION_GREATER: + code += ",depth_function_greater"; + break; + case DEPTH_FUNCTION_NOT_EQUAL: + code += ",depth_function_not_equal"; + break; + case DEPTH_FUNCTION_GREATER_OR_EQUAL: + code += ",depth_function_greater_or_equal"; + break; + case DEPTH_FUNCTION_ALWAYS: + code += ",depth_function_always"; + break; + case DEPTH_FUNCTION_NEVER: + code += ",depth_function_never"; + break; + case DEPTH_FUNCTION_MAX: + break; // Internal value, skip. + } + switch (cull_mode) { case CULL_BACK: code += ", cull_back"; @@ -2170,6 +2199,19 @@ BaseMaterial3D::DepthDrawMode BaseMaterial3D::get_depth_draw_mode() const { return depth_draw_mode; } +void BaseMaterial3D::set_depth_function(DepthFunction p_func) { + if (depth_function == p_func) { + return; + } + + depth_function = p_func; + _queue_shader_change(); +} + +BaseMaterial3D::DepthFunction BaseMaterial3D::get_depth_function() const { + return depth_function; +} + void BaseMaterial3D::set_cull_mode(CullMode p_mode) { if (cull_mode == p_mode) { return; @@ -2935,6 +2977,9 @@ void BaseMaterial3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_depth_draw_mode", "depth_draw_mode"), &BaseMaterial3D::set_depth_draw_mode); ClassDB::bind_method(D_METHOD("get_depth_draw_mode"), &BaseMaterial3D::get_depth_draw_mode); + ClassDB::bind_method(D_METHOD("set_depth_function", "depth_function"), &BaseMaterial3D::set_depth_function); + ClassDB::bind_method(D_METHOD("get_depth_function"), &BaseMaterial3D::get_depth_function); + ClassDB::bind_method(D_METHOD("set_cull_mode", "cull_mode"), &BaseMaterial3D::set_cull_mode); ClassDB::bind_method(D_METHOD("get_cull_mode"), &BaseMaterial3D::get_cull_mode); @@ -3064,6 +3109,7 @@ void BaseMaterial3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Subtract,Multiply,Premultiplied Alpha"), "set_blend_mode", "get_blend_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mode", PROPERTY_HINT_ENUM, "Back,Front,Disabled"), "set_cull_mode", "get_cull_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "depth_draw_mode", PROPERTY_HINT_ENUM, "Opaque Only,Always,Never"), "set_depth_draw_mode", "get_depth_draw_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "depth_function", PROPERTY_HINT_ENUM, "Less or Equal,Less,Equal,Greater,Not Equal,Greater or Equal,Always,Never"), "set_depth_function", "get_depth_function"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "no_depth_test"), "set_flag", "get_flag", FLAG_DISABLE_DEPTH_TEST); ADD_GROUP("Shading", ""); @@ -3300,6 +3346,15 @@ void BaseMaterial3D::_bind_methods() { BIND_ENUM_CONSTANT(DEPTH_DRAW_ALWAYS); BIND_ENUM_CONSTANT(DEPTH_DRAW_DISABLED); + BIND_ENUM_CONSTANT(DEPTH_FUNCTION_LESS_OR_EQUAL); + BIND_ENUM_CONSTANT(DEPTH_FUNCTION_LESS); + BIND_ENUM_CONSTANT(DEPTH_FUNCTION_EQUAL); + BIND_ENUM_CONSTANT(DEPTH_FUNCTION_GREATER); + BIND_ENUM_CONSTANT(DEPTH_FUNCTION_NOT_EQUAL); + BIND_ENUM_CONSTANT(DEPTH_FUNCTION_GREATER_OR_EQUAL); + BIND_ENUM_CONSTANT(DEPTH_FUNCTION_ALWAYS); + BIND_ENUM_CONSTANT(DEPTH_FUNCTION_NEVER); + BIND_ENUM_CONSTANT(CULL_BACK); BIND_ENUM_CONSTANT(CULL_FRONT); BIND_ENUM_CONSTANT(CULL_DISABLED); diff --git a/scene/resources/material.h b/scene/resources/material.h index 50a774e961f8..77288734691f 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -231,6 +231,18 @@ class BaseMaterial3D : public Material { DEPTH_DRAW_MAX }; + enum DepthFunction { + DEPTH_FUNCTION_LESS_OR_EQUAL, + DEPTH_FUNCTION_LESS, + DEPTH_FUNCTION_EQUAL, + DEPTH_FUNCTION_GREATER, + DEPTH_FUNCTION_NOT_EQUAL, + DEPTH_FUNCTION_GREATER_OR_EQUAL, + DEPTH_FUNCTION_ALWAYS, + DEPTH_FUNCTION_NEVER, + DEPTH_FUNCTION_MAX + }; + enum CullMode { CULL_BACK, CULL_FRONT, @@ -320,6 +332,7 @@ class BaseMaterial3D : public Material { uint64_t shading_mode : get_num_bits(SHADING_MODE_MAX - 1); uint64_t blend_mode : get_num_bits(BLEND_MODE_MAX - 1); uint64_t depth_draw_mode : get_num_bits(DEPTH_DRAW_MAX - 1); + uint64_t depth_function : get_num_bits(DEPTH_FUNCTION_MAX - 1); uint64_t cull_mode : get_num_bits(CULL_MAX - 1); uint64_t diffuse_mode : get_num_bits(DIFFUSE_MAX - 1); uint64_t specular_mode : get_num_bits(SPECULAR_MAX - 1); @@ -370,6 +383,7 @@ class BaseMaterial3D : public Material { mk.detail_uv = detail_uv; mk.blend_mode = blend_mode; mk.depth_draw_mode = depth_draw_mode; + mk.depth_function = depth_function; mk.cull_mode = cull_mode; mk.texture_filter = texture_filter; mk.transparency = transparency; @@ -536,6 +550,7 @@ class BaseMaterial3D : public Material { BlendMode blend_mode = BLEND_MODE_MIX; BlendMode detail_blend_mode = BLEND_MODE_MIX; DepthDrawMode depth_draw_mode = DEPTH_DRAW_OPAQUE_ONLY; + DepthFunction depth_function = DEPTH_FUNCTION_GREATER_OR_EQUAL; CullMode cull_mode = CULL_BACK; bool flags[FLAG_MAX] = {}; SpecularMode specular_mode = SPECULAR_SCHLICK_GGX; @@ -670,6 +685,9 @@ class BaseMaterial3D : public Material { void set_depth_draw_mode(DepthDrawMode p_mode); DepthDrawMode get_depth_draw_mode() const; + void set_depth_function(DepthFunction p_func); + DepthFunction get_depth_function() const; + void set_cull_mode(CullMode p_mode); CullMode get_cull_mode() const; @@ -792,6 +810,7 @@ VARIANT_ENUM_CAST(BaseMaterial3D::DetailUV) VARIANT_ENUM_CAST(BaseMaterial3D::Feature) VARIANT_ENUM_CAST(BaseMaterial3D::BlendMode) VARIANT_ENUM_CAST(BaseMaterial3D::DepthDrawMode) +VARIANT_ENUM_CAST(BaseMaterial3D::DepthFunction) VARIANT_ENUM_CAST(BaseMaterial3D::CullMode) VARIANT_ENUM_CAST(BaseMaterial3D::Flags) VARIANT_ENUM_CAST(BaseMaterial3D::DiffuseMode) 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 42e1f7b6dc4f..c72795262b2d 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 @@ -53,6 +53,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { int blend_mode = BLEND_MODE_MIX; int depth_testi = DEPTH_TEST_ENABLED; + int depth_functioni = DEPTH_FUNCTION_GREATER_OR_EQUAL; int alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF; int cull_modei = CULL_BACK; @@ -101,6 +102,15 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { actions.render_mode_values["depth_test_disabled"] = Pair(&depth_testi, DEPTH_TEST_DISABLED); + actions.render_mode_values["depth_function_less_or_equal"] = Pair(&depth_functioni, DEPTH_FUNCTION_LESS_OR_EQUAL); + actions.render_mode_values["depth_function_less"] = Pair(&depth_functioni, DEPTH_FUNCTION_LESS); + actions.render_mode_values["depth_function_equal"] = Pair(&depth_functioni, DEPTH_FUNCTION_EQUAL); + actions.render_mode_values["depth_function_greater"] = Pair(&depth_functioni, DEPTH_FUNCTION_GREATER); + actions.render_mode_values["depth_function_not_equal"] = Pair(&depth_functioni, DEPTH_FUNCTION_NOT_EQUAL); + actions.render_mode_values["depth_function_greater_or_equal"] = Pair(&depth_functioni, DEPTH_FUNCTION_GREATER_OR_EQUAL); + actions.render_mode_values["depth_function_always"] = Pair(&depth_functioni, DEPTH_FUNCTION_ALWAYS); + actions.render_mode_values["depth_function_never"] = Pair(&depth_functioni, DEPTH_FUNCTION_NEVER); + actions.render_mode_values["cull_disabled"] = Pair(&cull_modei, CULL_DISABLED); actions.render_mode_values["cull_front"] = Pair(&cull_modei, CULL_FRONT); actions.render_mode_values["cull_back"] = Pair(&cull_modei, CULL_BACK); @@ -151,6 +161,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { depth_draw = DepthDraw(depth_drawi); depth_test = DepthTest(depth_testi); + depth_function = DepthFunction(depth_functioni); cull_mode = Cull(cull_modei); uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps; uses_screen_texture = gen_code.uses_screen_texture; @@ -271,9 +282,22 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { if (depth_test != DEPTH_TEST_DISABLED) { depth_stencil_state.enable_depth_test = true; - depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_GREATER_OR_EQUAL; depth_stencil_state.enable_depth_write = depth_draw != DEPTH_DRAW_DISABLED ? true : false; + + RD::CompareOperator depth_function_rd_table[DEPTH_FUNCTION_MAX] = { + RD::COMPARE_OP_LESS_OR_EQUAL, + RD::COMPARE_OP_LESS, + RD::COMPARE_OP_EQUAL, + RD::COMPARE_OP_GREATER, + RD::COMPARE_OP_NOT_EQUAL, + RD::COMPARE_OP_GREATER_OR_EQUAL, + RD::COMPARE_OP_ALWAYS, + RD::COMPARE_OP_NEVER, + }; + + depth_stencil_state.depth_compare_operator = depth_function_rd_table[depth_function]; } + bool depth_pre_pass_enabled = bool(GLOBAL_GET("rendering/driver/depth_prepass/enable")); for (int i = 0; i < CULL_VARIANT_MAX; i++) { 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 d5332032f9f0..1af184a2d7d4 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 @@ -121,6 +121,18 @@ class SceneShaderForwardClustered { DEPTH_TEST_ENABLED }; + enum DepthFunction { + DEPTH_FUNCTION_LESS_OR_EQUAL, + DEPTH_FUNCTION_LESS, + DEPTH_FUNCTION_EQUAL, + DEPTH_FUNCTION_GREATER, + DEPTH_FUNCTION_NOT_EQUAL, + DEPTH_FUNCTION_GREATER_OR_EQUAL, + DEPTH_FUNCTION_ALWAYS, + DEPTH_FUNCTION_NEVER, + DEPTH_FUNCTION_MAX + }; + enum Cull { CULL_DISABLED, CULL_FRONT, @@ -155,6 +167,7 @@ class SceneShaderForwardClustered { String code; DepthDraw depth_draw = DEPTH_DRAW_OPAQUE; + DepthFunction depth_function = DEPTH_FUNCTION_GREATER_OR_EQUAL; DepthTest depth_test = DEPTH_TEST_ENABLED; bool uses_point_size = false; 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 cf661bb8f4bf..fc28fd4ef0f6 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 @@ -55,6 +55,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { int blend_mode = BLEND_MODE_MIX; int depth_testi = DEPTH_TEST_ENABLED; + int depth_functioni = DEPTH_FUNCTION_GREATER_OR_EQUAL; int alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF; int cull = CULL_BACK; @@ -102,6 +103,15 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { actions.render_mode_values["depth_test_disabled"] = Pair(&depth_testi, DEPTH_TEST_DISABLED); + actions.render_mode_values["depth_function_less_or_equal"] = Pair(&depth_functioni, DEPTH_FUNCTION_LESS_OR_EQUAL); + actions.render_mode_values["depth_function_less"] = Pair(&depth_functioni, DEPTH_FUNCTION_LESS); + actions.render_mode_values["depth_function_equal"] = Pair(&depth_functioni, DEPTH_FUNCTION_EQUAL); + actions.render_mode_values["depth_function_greater"] = Pair(&depth_functioni, DEPTH_FUNCTION_GREATER); + actions.render_mode_values["depth_function_not_equal"] = Pair(&depth_functioni, DEPTH_FUNCTION_NOT_EQUAL); + actions.render_mode_values["depth_function_greater_or_equal"] = Pair(&depth_functioni, DEPTH_FUNCTION_GREATER_OR_EQUAL); + actions.render_mode_values["depth_function_always"] = Pair(&depth_functioni, DEPTH_FUNCTION_ALWAYS); + actions.render_mode_values["depth_function_never"] = Pair(&depth_functioni, DEPTH_FUNCTION_NEVER); + actions.render_mode_values["cull_disabled"] = Pair(&cull, CULL_DISABLED); actions.render_mode_values["cull_front"] = Pair(&cull, CULL_FRONT); actions.render_mode_values["cull_back"] = Pair(&cull, CULL_BACK); @@ -152,6 +162,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { depth_draw = DepthDraw(depth_drawi); depth_test = DepthTest(depth_testi); + depth_function = DepthFunction(depth_functioni); uses_vertex_time = gen_code.uses_vertex_time; uses_fragment_time = gen_code.uses_fragment_time; uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps; @@ -282,8 +293,20 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { if (depth_test != DEPTH_TEST_DISABLED) { depth_stencil_state.enable_depth_test = true; - depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_GREATER_OR_EQUAL; depth_stencil_state.enable_depth_write = depth_draw != DEPTH_DRAW_DISABLED ? true : false; + + RD::CompareOperator depth_function_rd_table[DEPTH_FUNCTION_MAX] = { + RD::COMPARE_OP_LESS_OR_EQUAL, + RD::COMPARE_OP_LESS, + RD::COMPARE_OP_EQUAL, + RD::COMPARE_OP_GREATER, + RD::COMPARE_OP_NOT_EQUAL, + RD::COMPARE_OP_GREATER_OR_EQUAL, + RD::COMPARE_OP_ALWAYS, + RD::COMPARE_OP_NEVER, + }; + + depth_stencil_state.depth_compare_operator = depth_function_rd_table[depth_function]; } for (int i = 0; i < CULL_VARIANT_MAX; i++) { 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 833b06c1e31b..e6ff7e547e90 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 @@ -71,6 +71,18 @@ class SceneShaderForwardMobile { DEPTH_DRAW_ALWAYS }; + enum DepthFunction { + DEPTH_FUNCTION_LESS_OR_EQUAL, + DEPTH_FUNCTION_LESS, + DEPTH_FUNCTION_EQUAL, + DEPTH_FUNCTION_GREATER, + DEPTH_FUNCTION_NOT_EQUAL, + DEPTH_FUNCTION_GREATER_OR_EQUAL, + DEPTH_FUNCTION_ALWAYS, + DEPTH_FUNCTION_NEVER, + DEPTH_FUNCTION_MAX + }; + enum DepthTest { DEPTH_TEST_DISABLED, DEPTH_TEST_ENABLED @@ -109,6 +121,7 @@ class SceneShaderForwardMobile { String code; DepthDraw depth_draw; + DepthFunction depth_function; DepthTest depth_test; bool uses_point_size = false; diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 076bd8def4a8..d8d7cc197bfc 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -877,6 +877,13 @@ class ShaderLanguage { options.push_back(p_arg5); options.push_back(p_arg6); } + + ModeInfo(const StringName &p_name, std::initializer_list p_args) : + name(p_name) { + for (const StringName &arg : p_args) { + options.push_back(arg); + } + } }; struct FunctionInfo { diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index de396cd18baf..a3f92b8c5303 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -211,6 +211,7 @@ ShaderTypes::ShaderTypes() { { shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("blend"), "mix", "add", "sub", "mul", "premul_alpha" }); shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("depth_draw"), "opaque", "always", "never" }); + shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("depth_function"), { "less_or_equal", "less", "equal", "greater", "not_equal", "greater_or_equal", "always", "never" } }); shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("depth_prepass_alpha") }); shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("depth_test_disabled") }); shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("sss_mode_skin") });