Skip to content

Commit

Permalink
Add depth function for spatial materials
Browse files Browse the repository at this point in the history
  • Loading branch information
apples committed Jul 20, 2024
1 parent ff8a278 commit 47ff5a9
Show file tree
Hide file tree
Showing 13 changed files with 240 additions and 8 deletions.
28 changes: 28 additions & 0 deletions doc/classes/BaseMaterial3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@
<member name="depth_draw_mode" type="int" setter="set_depth_draw_mode" getter="get_depth_draw_mode" enum="BaseMaterial3D.DepthDrawMode" default="0">
Determines when depth rendering takes place. See [enum DepthDrawMode]. See also [member transparency].
</member>
<member name="depth_function" type="int" setter="set_depth_function" getter="get_depth_function" enum="BaseMaterial3D.DepthFunction" default="0">
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].
</member>
<member name="detail_albedo" type="Texture2D" setter="set_texture" getter="get_texture">
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].
Expand Down Expand Up @@ -631,6 +635,30 @@
<constant name="DEPTH_DRAW_DISABLED" value="2" enum="DepthDrawMode">
Objects will not write their depth to the depth buffer, even during the depth prepass (if enabled).
</constant>
<constant name="DEPTH_FUNCTION_LESS_OR_EQUAL" value="0" enum="DepthFunction">
Depth check succeeds if less than or equal to existing depth.
</constant>
<constant name="DEPTH_FUNCTION_LESS" value="1" enum="DepthFunction">
Depth check succeeds if less than existing depth.
</constant>
<constant name="DEPTH_FUNCTION_EQUAL" value="2" enum="DepthFunction">
Depth check succeeds if equal to existing depth.
</constant>
<constant name="DEPTH_FUNCTION_GREATER" value="3" enum="DepthFunction">
Depth check succeeds if greater than existing depth.
</constant>
<constant name="DEPTH_FUNCTION_NOT_EQUAL" value="4" enum="DepthFunction">
Depth check succeeds if not equal to existing depth.
</constant>
<constant name="DEPTH_FUNCTION_GREATER_OR_EQUAL" value="5" enum="DepthFunction">
Default depth function. Depth check succeeds if greater than or equal to existing depth.
</constant>
<constant name="DEPTH_FUNCTION_ALWAYS" value="6" enum="DepthFunction">
Depth check always succeeds.
</constant>
<constant name="DEPTH_FUNCTION_NEVER" value="7" enum="DepthFunction">
Depth check never succeeds.
</constant>
<constant name="CULL_BACK" value="0" enum="CullMode">
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.
</constant>
Expand Down
15 changes: 9 additions & 6 deletions drivers/gles3/rasterizer_scene_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -2493,7 +2493,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &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);
Expand Down Expand Up @@ -2531,7 +2531,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &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;
Expand Down Expand Up @@ -2591,6 +2591,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &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);

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -3652,7 +3655,7 @@ void RasterizerSceneGLES3::_render_uv2(const PagedArray<RenderGeometryInstance *
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);

TightLocalVector<GLenum> draw_buffers;
draw_buffers.push_back(GL_COLOR_ATTACHMENT0);
Expand Down Expand Up @@ -3745,7 +3748,7 @@ void RasterizerSceneGLES3::_render_buffers_debug_draw(Ref<RenderSceneBuffersGLES
glViewport(0, 0, shadow_atlas_size, shadow_atlas_size);
glActiveTexture(GL_TEXTURE0);
scene_state.enable_gl_depth_draw(true);
glDepthFunc(GL_ALWAYS);
scene_state.set_gl_depth_func(GLES3::SceneShaderData::DEPTH_FUNCTION_ALWAYS);
scene_state.set_gl_cull_mode(GLES3::SceneShaderData::CULL_DISABLED);

// Loop through quadrants and copy shadows over.
Expand Down
22 changes: 22 additions & 0 deletions drivers/gles3/rasterizer_scene_gles3.h
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
bool used_depth_prepass = false;

GLES3::SceneShaderData::BlendMode current_blend_mode = GLES3::SceneShaderData::BLEND_MODE_MIX;
GLES3::SceneShaderData::DepthFunction current_depth_function = GLES3::SceneShaderData::DEPTH_FUNCTION_GREATER_OR_EQUAL;
GLES3::SceneShaderData::Cull cull_mode = GLES3::SceneShaderData::CULL_BACK;

bool current_blend_enabled = false;
Expand All @@ -482,6 +483,9 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
current_depth_draw_enabled = false;
glDisable(GL_DEPTH_TEST);
current_depth_test_enabled = false;

glDepthFunc(GL_GEQUAL);
current_depth_function = GLES3::SceneShaderData::DEPTH_FUNCTION_GREATER_OR_EQUAL;
}

void set_gl_cull_mode(GLES3::SceneShaderData::Cull p_mode) {
Expand Down Expand Up @@ -539,6 +543,24 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
}
}

void set_gl_depth_func(GLES3::SceneShaderData::DepthFunction p_depth_func) {
if (current_depth_function != p_depth_func) {
GLenum depth_function_table[GLES3::SceneShaderData::DEPTH_FUNCTION_MAX] = {
GL_LEQUAL,
GL_LESS,
GL_EQUAL,
GL_GREATER,
GL_NOTEQUAL,
GL_GEQUAL,
GL_ALWAYS,
GL_NEVER,
};

glDepthFunc(depth_function_table[p_depth_func]);
current_depth_function = p_depth_func;
}
}

bool texscreen_copied = false;
bool used_screen_texture = false;
bool used_normal_texture = false;
Expand Down
11 changes: 11 additions & 0 deletions drivers/gles3/storage/material_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2894,6 +2894,7 @@ void SceneShaderData::set_code(const String &p_code) {
// Actual enums set further down after compilation.
int blend_modei = BLEND_MODE_MIX;
int depth_testi = DEPTH_TEST_ENABLED;
int depth_functioni = DEPTH_FUNCTION_GREATER_OR_EQUAL;
int alpha_antialiasing_modei = ALPHA_ANTIALIASING_OFF;
int cull_modei = CULL_BACK;
int depth_drawi = DEPTH_DRAW_OPAQUE;
Expand All @@ -2918,6 +2919,15 @@ void SceneShaderData::set_code(const String &p_code) {

actions.render_mode_values["depth_test_disabled"] = Pair<int *, int>(&depth_testi, DEPTH_TEST_DISABLED);

actions.render_mode_values["depth_function_less_or_equal"] = Pair<int *, int>(&depth_functioni, DEPTH_FUNCTION_LESS_OR_EQUAL);
actions.render_mode_values["depth_function_less"] = Pair<int *, int>(&depth_functioni, DEPTH_FUNCTION_LESS);
actions.render_mode_values["depth_function_equal"] = Pair<int *, int>(&depth_functioni, DEPTH_FUNCTION_EQUAL);
actions.render_mode_values["depth_function_greater"] = Pair<int *, int>(&depth_functioni, DEPTH_FUNCTION_GREATER);
actions.render_mode_values["depth_function_not_equal"] = Pair<int *, int>(&depth_functioni, DEPTH_FUNCTION_NOT_EQUAL);
actions.render_mode_values["depth_function_greater_or_equal"] = Pair<int *, int>(&depth_functioni, DEPTH_FUNCTION_GREATER_OR_EQUAL);
actions.render_mode_values["depth_function_always"] = Pair<int *, int>(&depth_functioni, DEPTH_FUNCTION_ALWAYS);
actions.render_mode_values["depth_function_never"] = Pair<int *, int>(&depth_functioni, DEPTH_FUNCTION_NEVER);

actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull_modei, CULL_DISABLED);
actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull_modei, CULL_FRONT);
actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull_modei, CULL_BACK);
Expand Down Expand Up @@ -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.
Expand Down
13 changes: 13 additions & 0 deletions drivers/gles3/storage/material_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down
55 changes: 55 additions & 0 deletions scene/resources/material.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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", "");
Expand Down Expand Up @@ -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);
Expand Down
19 changes: 19 additions & 0 deletions scene/resources/material.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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)
Expand Down
Loading

0 comments on commit 47ff5a9

Please sign in to comment.