diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml
index 6fd4396745..9cc1451d9a 100644
--- a/doc/classes/BaseMaterial3D.xml
+++ b/doc/classes/BaseMaterial3D.xml
@@ -159,6 +159,10 @@
Determines when depth rendering takes place. See also [member transparency].
+
+ Determines which comparison operator is used when testing depth. See [enum DepthTest].
+ [b]Note:[/b] Changing [member depth_test] 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].
@@ -661,6 +665,12 @@
Objects will not write their depth to the depth buffer, even during the depth prepass (if enabled).
+
+ Depth test will discard the pixel if it is behind other pixels.
+
+
+ Depth test will discard the pixel if it is in front of other pixels. Useful for stencil effects.
+
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 6d0d59ce42..84be199a0f 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -32,6 +32,7 @@
#include "drivers/gles3/effects/copy_effects.h"
#include "drivers/gles3/effects/feed_effects.h"
+#include "drivers/gles3/storage/material_storage.h"
#include "rasterizer_gles3.h"
#include "storage/config.h"
#include "storage/mesh_storage.h"
@@ -223,10 +224,10 @@ void RasterizerSceneGLES3::_geometry_instance_add_surface_with_material(Geometry
flags |= GeometryInstanceSurface::FLAG_USES_DOUBLE_SIDED_SHADOWS;
}
- 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) {
+ 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_ENABLED) {
//material is only meant for alpha pass
flags |= GeometryInstanceSurface::FLAG_PASS_ALPHA;
- 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)) {
+ 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_ENABLED)) {
flags |= GeometryInstanceSurface::FLAG_PASS_DEPTH;
flags |= GeometryInstanceSurface::FLAG_PASS_SHADOW;
}
@@ -2184,7 +2185,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(GL_GREATER);
glColorMask(0, 0, 0, 0);
glDrawBuffers(0, nullptr);
@@ -2503,7 +2504,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(GL_GEQUAL);
scene_state.enable_gl_scissor_test(false);
glColorMask(0, 0, 0, 0);
@@ -2541,7 +2542,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(GL_GEQUAL);
{
GLuint db = GL_COLOR_ATTACHMENT0;
@@ -2635,6 +2636,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(GL_GEQUAL);
scene_state.enable_gl_blend(false);
scene_state.set_gl_cull_mode(RS::CULL_MODE_BACK);
@@ -3016,7 +3018,13 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
}
if constexpr (p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) {
- scene_state.enable_gl_depth_test(shader->depth_test == GLES3::SceneShaderData::DEPTH_TEST_ENABLED);
+ scene_state.enable_gl_depth_test(shader->depth_test != GLES3::SceneShaderData::DEPTH_TEST_DISABLED);
+ }
+
+ if (shader->depth_test == GLES3::SceneShaderData::DEPTH_TEST_ENABLED_INVERTED) {
+ scene_state.set_gl_depth_func(GL_LESS);
+ } else {
+ scene_state.set_gl_depth_func(GL_GEQUAL);
}
if constexpr (p_pass_mode != PASS_MODE_SHADOW) {
@@ -3713,7 +3721,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(GL_GREATER);
glDrawBuffers(0, nullptr);
@@ -3759,7 +3767,7 @@ void RasterizerSceneGLES3::_render_uv2(const PagedArray draw_buffers;
draw_buffers.push_back(GL_COLOR_ATTACHMENT0);
@@ -3852,7 +3860,7 @@ void RasterizerSceneGLES3::_render_buffers_debug_draw(Ref(&depth_drawi, DEPTH_DRAW_OPAQUE);
actions.render_mode_values["depth_draw_always"] = Pair(&depth_drawi, DEPTH_DRAW_ALWAYS);
- actions.render_mode_values["depth_test_disabled"] = Pair(&depth_testi, DEPTH_TEST_DISABLED);
+ actions.render_mode_values["depth_test_disabled"] = Pair(&depth_test_disabledi, 1);
+ actions.render_mode_values["depth_test_inverted"] = Pair(&depth_test_invertedi, 1);
actions.render_mode_values["cull_disabled"] = Pair(&cull_modei, RS::CULL_MODE_DISABLED);
actions.render_mode_values["cull_front"] = Pair(&cull_modei, RS::CULL_MODE_FRONT);
@@ -3026,7 +3028,13 @@ void SceneShaderData::set_code(const String &p_code) {
blend_mode = BlendMode(blend_modei);
alpha_antialiasing_mode = AlphaAntiAliasing(alpha_antialiasing_modei);
depth_draw = DepthDraw(depth_drawi);
- depth_test = DepthTest(depth_testi);
+ if (depth_test_disabledi) {
+ depth_test = DEPTH_TEST_DISABLED;
+ } else if (depth_test_invertedi) {
+ depth_test = DEPTH_TEST_ENABLED_INVERTED;
+ } else {
+ depth_test = DEPTH_TEST_ENABLED;
+ }
cull_mode = RS::CullMode(cull_modei);
vertex_input_mask = RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL; // We can always read vertices and normals.
@@ -3114,7 +3122,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_prepass_alpha && !(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_ENABLED));
}
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 9f2b214f3e..dfd469354a 100644
--- a/drivers/gles3/storage/material_storage.h
+++ b/drivers/gles3/storage/material_storage.h
@@ -257,7 +257,8 @@ struct SceneShaderData : public ShaderData {
enum DepthTest {
DEPTH_TEST_DISABLED,
- DEPTH_TEST_ENABLED
+ DEPTH_TEST_ENABLED,
+ DEPTH_TEST_ENABLED_INVERTED,
};
enum AlphaAntiAliasing {
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 0bd2805c8c..b5d54a1eaa 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -861,6 +861,17 @@ void BaseMaterial3D::_update_shader() {
}
if (flags[FLAG_DISABLE_DEPTH_TEST]) {
code += ", depth_test_disabled";
+ } else {
+ switch (depth_test) {
+ case DEPTH_TEST_DEFAULT:
+ // depth_test_default is the default behavior, no need to emit it here.
+ break;
+ case DEPTH_TEST_INVERTED:
+ code += ", depth_test_inverted";
+ break;
+ case DEPTH_TEST_MAX:
+ break; // Internal value, skip.
+ }
}
if (flags[FLAG_PARTICLE_TRAILS_MODE]) {
code += ", particle_trails";
@@ -2354,6 +2365,19 @@ BaseMaterial3D::DepthDrawMode BaseMaterial3D::get_depth_draw_mode() const {
return depth_draw_mode;
}
+void BaseMaterial3D::set_depth_test(DepthTest p_func) {
+ if (depth_test == p_func) {
+ return;
+ }
+
+ depth_test = p_func;
+ _queue_shader_change();
+}
+
+BaseMaterial3D::DepthTest BaseMaterial3D::get_depth_test() const {
+ return depth_test;
+}
+
void BaseMaterial3D::set_cull_mode(CullMode p_mode) {
if (cull_mode == p_mode) {
return;
@@ -2410,7 +2434,8 @@ void BaseMaterial3D::set_flag(Flags p_flag, bool p_enabled) {
p_flag == FLAG_UV1_USE_TRIPLANAR ||
p_flag == FLAG_UV2_USE_TRIPLANAR ||
p_flag == FLAG_USE_Z_CLIP_SCALE ||
- p_flag == FLAG_USE_FOV_OVERRIDE) {
+ p_flag == FLAG_USE_FOV_OVERRIDE ||
+ p_flag == FLAG_DISABLE_DEPTH_TEST) {
notify_property_list_changed();
}
@@ -2565,6 +2590,10 @@ void BaseMaterial3D::_validate_property(PropertyInfo &p_property) const {
p_property.usage = PROPERTY_USAGE_NONE;
}
+ if (p_property.name == "depth_test" && flags[FLAG_DISABLE_DEPTH_TEST]) {
+ p_property.usage = PROPERTY_USAGE_NONE;
+ }
+
if (flags[FLAG_SUBSURFACE_MODE_SKIN] && (p_property.name == "subsurf_scatter_transmittance_color" || p_property.name == "subsurf_scatter_transmittance_texture")) {
p_property.usage = PROPERTY_USAGE_NONE;
}
@@ -3133,6 +3162,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_test", "depth_test"), &BaseMaterial3D::set_depth_test);
+ ClassDB::bind_method(D_METHOD("get_depth_test"), &BaseMaterial3D::get_depth_test);
+
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);
@@ -3269,6 +3301,7 @@ void BaseMaterial3D::_bind_methods() {
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_PROPERTYI(PropertyInfo(Variant::BOOL, "no_depth_test"), "set_flag", "get_flag", FLAG_DISABLE_DEPTH_TEST);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "depth_test", PROPERTY_HINT_ENUM, "Default,Inverted"), "set_depth_test", "get_depth_test");
ADD_GROUP("Shading", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "shading_mode", PROPERTY_HINT_ENUM, "Unshaded,Per-Pixel,Per-Vertex"), "set_shading_mode", "get_shading_mode");
@@ -3518,6 +3551,9 @@ void BaseMaterial3D::_bind_methods() {
BIND_ENUM_CONSTANT(DEPTH_DRAW_ALWAYS);
BIND_ENUM_CONSTANT(DEPTH_DRAW_DISABLED);
+ BIND_ENUM_CONSTANT(DEPTH_TEST_DEFAULT);
+ BIND_ENUM_CONSTANT(DEPTH_TEST_INVERTED);
+
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 aca637713e..8a5141eb41 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -238,6 +238,12 @@ public:
DEPTH_DRAW_MAX
};
+ enum DepthTest {
+ DEPTH_TEST_DEFAULT,
+ DEPTH_TEST_INVERTED,
+ DEPTH_TEST_MAX
+ };
+
enum CullMode {
CULL_BACK,
CULL_FRONT,
@@ -330,6 +336,7 @@ private:
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_test : get_num_bits(DEPTH_TEST_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);
@@ -381,6 +388,7 @@ private:
mk.detail_uv = detail_uv;
mk.blend_mode = blend_mode;
mk.depth_draw_mode = depth_draw_mode;
+ mk.depth_test = depth_test;
mk.cull_mode = cull_mode;
mk.texture_filter = texture_filter;
mk.transparency = transparency;
@@ -553,6 +561,7 @@ private:
BlendMode blend_mode = BLEND_MODE_MIX;
BlendMode detail_blend_mode = BLEND_MODE_MIX;
DepthDrawMode depth_draw_mode = DEPTH_DRAW_OPAQUE_ONLY;
+ DepthTest depth_test = DEPTH_TEST_DEFAULT;
CullMode cull_mode = CULL_BACK;
bool flags[FLAG_MAX] = {};
SpecularMode specular_mode = SPECULAR_SCHLICK_GGX;
@@ -688,6 +697,9 @@ public:
void set_depth_draw_mode(DepthDrawMode p_mode);
DepthDrawMode get_depth_draw_mode() const;
+ void set_depth_test(DepthTest p_func);
+ DepthTest get_depth_test() const;
+
void set_cull_mode(CullMode p_mode);
CullMode get_cull_mode() const;
@@ -816,6 +828,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::DepthTest)
VARIANT_ENUM_CAST(BaseMaterial3D::CullMode)
VARIANT_ENUM_CAST(BaseMaterial3D::Flags)
VARIANT_ENUM_CAST(BaseMaterial3D::DiffuseMode)
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index 733771df29..a76dd797ae 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -1886,6 +1886,29 @@ void VisualShader::_get_property_list(List *p_list) const {
for (int i = 0; i < rmodes.size(); i++) {
const ShaderLanguage::ModeInfo &info = rmodes[i];
+ // Special handling for depth_test.
+ if (info.name == "depth_test") {
+ toggles.insert("depth_test_disabled");
+
+ const String begin = String(info.name);
+
+ for (int j = 0; j < info.options.size(); j++) {
+ if (info.options[j] == "disabled") {
+ continue;
+ }
+
+ const String option = String(info.options[j]).capitalize();
+
+ if (!blend_mode_enums.has(begin)) {
+ blend_mode_enums[begin] = vformat("%s:%s", option, j);
+ } else {
+ blend_mode_enums[begin] += "," + vformat("%s:%s", option, j);
+ }
+ }
+
+ continue;
+ }
+
if (!info.options.is_empty()) {
const String begin = String(info.name);
@@ -2550,6 +2573,23 @@ void VisualShader::_update_shader() const {
const ShaderLanguage::ModeInfo &info = rmodes[i];
const String temp = String(info.name);
+ // Special handling for depth_test.
+ if (temp == "depth_test") {
+ if (flags.has("depth_test_disabled")) {
+ flag_names.push_back("depth_test_disabled");
+ } else {
+ if (!render_mode.is_empty()) {
+ render_mode += ", ";
+ }
+ if (modes.has(temp) && modes[temp] < info.options.size()) {
+ render_mode += temp + "_" + info.options[modes[temp]];
+ } else {
+ render_mode += temp + "_" + info.options[0];
+ }
+ }
+ continue;
+ }
+
if (!info.options.is_empty()) {
if (!render_mode.is_empty()) {
render_mode += ", ";
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 dfb1634f1f..e75302f345 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
@@ -52,7 +52,8 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
ShaderCompiler::GeneratedCode gen_code;
blend_mode = BLEND_MODE_MIX;
- depth_testi = DEPTH_TEST_ENABLED;
+ depth_test_disabledi = 0;
+ depth_test_invertedi = 0;
alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
int cull_modei = RS::CULL_MODE_BACK;
@@ -101,7 +102,8 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
actions.render_mode_values["depth_draw_opaque"] = Pair(&depth_drawi, DEPTH_DRAW_OPAQUE);
actions.render_mode_values["depth_draw_always"] = Pair(&depth_drawi, DEPTH_DRAW_ALWAYS);
- actions.render_mode_values["depth_test_disabled"] = Pair(&depth_testi, DEPTH_TEST_DISABLED);
+ actions.render_mode_values["depth_test_disabled"] = Pair(&depth_test_disabledi, 1);
+ actions.render_mode_values["depth_test_inverted"] = Pair(&depth_test_invertedi, 1);
actions.render_mode_values["cull_disabled"] = Pair(&cull_modei, RS::CULL_MODE_DISABLED);
actions.render_mode_values["cull_front"] = Pair(&cull_modei, RS::CULL_MODE_FRONT);
@@ -164,7 +166,13 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
}
depth_draw = DepthDraw(depth_drawi);
- depth_test = DepthTest(depth_testi);
+ if (depth_test_disabledi) {
+ depth_test = DEPTH_TEST_DISABLED;
+ } else if (depth_test_invertedi) {
+ depth_test = DEPTH_TEST_ENABLED_INVERTED;
+ } else {
+ depth_test = DEPTH_TEST_ENABLED;
+ }
cull_mode = RS::CullMode(cull_modei);
uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
uses_screen_texture = gen_code.uses_screen_texture;
@@ -219,7 +227,7 @@ bool SceneShaderForwardClustered::ShaderData::casts_shadows() const {
bool has_base_alpha = (uses_alpha && (!uses_alpha_clip || uses_alpha_antialiasing)) || has_read_screen_alpha;
bool has_alpha = has_base_alpha || uses_blend_alpha;
- return !has_alpha || (uses_depth_prepass_alpha && !(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_ENABLED));
}
RS::ShaderNativeSourceCode SceneShaderForwardClustered::ShaderData::get_native_source_code() const {
@@ -318,8 +326,12 @@ void SceneShaderForwardClustered::ShaderData::_create_pipeline(PipelineKey p_pip
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;
+ depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_GREATER_OR_EQUAL;
+
+ if (depth_test == DEPTH_TEST_ENABLED_INVERTED) {
+ depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS;
+ }
}
bool depth_pre_pass_enabled = bool(GLOBAL_GET_CACHED(bool, "rendering/driver/depth_prepass/enable"));
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 f9d09b1c40..5090051b56 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
@@ -150,7 +150,8 @@ public:
enum DepthTest {
DEPTH_TEST_DISABLED,
- DEPTH_TEST_ENABLED
+ DEPTH_TEST_ENABLED,
+ DEPTH_TEST_ENABLED_INVERTED,
};
enum CullVariant {
@@ -213,7 +214,8 @@ public:
DepthTest depth_test = DEPTH_TEST_ENABLED;
int blend_mode = BLEND_MODE_MIX;
- int depth_testi = DEPTH_TEST_ENABLED;
+ int depth_test_disabledi = 0;
+ int depth_test_invertedi = 0;
int alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
bool uses_point_size = false;
@@ -257,13 +259,13 @@ public:
bool has_blend_alpha = uses_blend_alpha;
bool has_alpha = has_base_alpha || has_blend_alpha;
bool no_depth_draw = depth_draw == DEPTH_DRAW_DISABLED;
- bool no_depth_test = depth_test == DEPTH_TEST_DISABLED;
+ bool no_depth_test = depth_test != DEPTH_TEST_ENABLED;
return has_alpha || has_read_screen_alpha || no_depth_draw || no_depth_test;
}
_FORCE_INLINE_ bool uses_depth_in_alpha_pass() const {
bool no_depth_draw = depth_draw == DEPTH_DRAW_DISABLED;
- bool no_depth_test = depth_test == DEPTH_TEST_DISABLED;
+ bool no_depth_test = depth_test != DEPTH_TEST_ENABLED;
return (uses_depth_prepass_alpha || uses_alpha_antialiasing) && !(no_depth_draw || no_depth_test);
}
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 732d430531..223cfd181c 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
@@ -54,7 +54,8 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
ShaderCompiler::GeneratedCode gen_code;
blend_mode = BLEND_MODE_MIX;
- depth_testi = DEPTH_TEST_ENABLED;
+ depth_test_disabledi = 0;
+ depth_test_invertedi = 0;
alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
cull_mode = RS::CULL_MODE_BACK;
@@ -101,7 +102,8 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
actions.render_mode_values["depth_draw_opaque"] = Pair(&depth_drawi, DEPTH_DRAW_OPAQUE);
actions.render_mode_values["depth_draw_always"] = Pair(&depth_drawi, DEPTH_DRAW_ALWAYS);
- actions.render_mode_values["depth_test_disabled"] = Pair(&depth_testi, DEPTH_TEST_DISABLED);
+ actions.render_mode_values["depth_test_disabled"] = Pair(&depth_test_disabledi, 1);
+ actions.render_mode_values["depth_test_inverted"] = Pair(&depth_test_invertedi, 1);
actions.render_mode_values["cull_disabled"] = Pair(&cull_mode, RS::CULL_MODE_DISABLED);
actions.render_mode_values["cull_front"] = Pair(&cull_mode, RS::CULL_MODE_FRONT);
@@ -159,7 +161,13 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
}
depth_draw = DepthDraw(depth_drawi);
- depth_test = DepthTest(depth_testi);
+ if (depth_test_disabledi) {
+ depth_test = DEPTH_TEST_DISABLED;
+ } else if (depth_test_invertedi) {
+ depth_test = DEPTH_TEST_ENABLED_INVERTED;
+ } else {
+ depth_test = DEPTH_TEST_ENABLED;
+ }
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;
@@ -224,7 +232,7 @@ bool SceneShaderForwardMobile::ShaderData::casts_shadows() const {
bool has_base_alpha = (uses_alpha && (!uses_alpha_clip || uses_alpha_antialiasing)) || has_read_screen_alpha;
bool has_alpha = has_base_alpha || uses_blend_alpha;
- return !has_alpha || (uses_depth_prepass_alpha && !(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_ENABLED));
}
RS::ShaderNativeSourceCode SceneShaderForwardMobile::ShaderData::get_native_source_code() const {
@@ -276,8 +284,12 @@ void SceneShaderForwardMobile::ShaderData::_create_pipeline(PipelineKey p_pipeli
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;
+ depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_GREATER_OR_EQUAL;
+
+ if (depth_test == DEPTH_TEST_ENABLED_INVERTED) {
+ depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS;
+ }
}
RD::RenderPrimitive primitive_rd_table[RS::PRIMITIVE_MAX] = {
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 29fc5bb2a5..18af561e23 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
@@ -148,7 +148,8 @@ public:
enum DepthTest {
DEPTH_TEST_DISABLED,
- DEPTH_TEST_ENABLED
+ DEPTH_TEST_ENABLED,
+ DEPTH_TEST_ENABLED_INVERTED,
};
enum CullVariant {
@@ -211,7 +212,8 @@ public:
DepthTest depth_test;
int blend_mode = BLEND_MODE_MIX;
- int depth_testi = DEPTH_TEST_ENABLED;
+ int depth_test_disabledi = 0;
+ int depth_test_invertedi = 0;
int alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
int cull_mode = RS::CULL_MODE_BACK;
@@ -253,13 +255,13 @@ public:
bool has_blend_alpha = uses_blend_alpha;
bool has_alpha = has_base_alpha || has_blend_alpha;
bool no_depth_draw = depth_draw == DEPTH_DRAW_DISABLED;
- bool no_depth_test = depth_test == DEPTH_TEST_DISABLED;
+ bool no_depth_test = depth_test != DEPTH_TEST_ENABLED;
return has_alpha || has_read_screen_alpha || no_depth_draw || no_depth_test;
}
_FORCE_INLINE_ bool uses_depth_in_alpha_pass() const {
bool no_depth_draw = depth_draw == DEPTH_DRAW_DISABLED;
- bool no_depth_test = depth_test == DEPTH_TEST_DISABLED;
+ bool no_depth_test = depth_test != DEPTH_TEST_ENABLED;
return (uses_depth_prepass_alpha || uses_alpha_antialiasing) && !(no_depth_draw || no_depth_test);
}
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index 233221735a..bee2f5bdc4 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -937,6 +937,13 @@ public:
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 fc90b50966..c64df961ba 100644
--- a/servers/rendering/shader_types.cpp
+++ b/servers/rendering/shader_types.cpp
@@ -226,7 +226,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_prepass_alpha") });
- shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("depth_test_disabled") });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("depth_test"), { "default", "disabled", "inverted" } });
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("sss_mode_skin") });
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("cull"), "back", "front", "disabled" });
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("unshaded") });