Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve behaviour of clip_children by clipping to parent alpha value but still retaining parent color #67043

Merged
merged 2 commits into from
Oct 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion doc/classes/CanvasItem.xml
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@
</method>
</methods>
<members>
<member name="clip_children" type="bool" setter="set_clip_children" getter="is_clipping_children" default="false">
<member name="clip_children" type="int" setter="set_clip_children_mode" getter="get_clip_children_mode" enum="CanvasItem.ClipChildrenMode" default="0">
Allows the current node to clip children nodes, essentially acting as a mask.
</member>
<member name="light_mask" type="int" setter="set_light_mask" getter="get_light_mask" default="1">
Expand Down Expand Up @@ -653,5 +653,13 @@
<constant name="TEXTURE_REPEAT_MAX" value="4" enum="TextureRepeat">
Represents the size of the [enum TextureRepeat] enum.
</constant>
<constant name="CLIP_CHILDREN_DISABLED" value="0" enum="ClipChildrenMode">
</constant>
<constant name="CLIP_CHILDREN_ONLY" value="1" enum="ClipChildrenMode">
</constant>
<constant name="CLIP_CHILDREN_AND_DRAW" value="2" enum="ClipChildrenMode">
</constant>
<constant name="CLIP_CHILDREN_MAX" value="3" enum="ClipChildrenMode">
</constant>
</constants>
</class>
6 changes: 4 additions & 2 deletions doc/classes/RenderingServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4576,9 +4576,11 @@
</constant>
<constant name="CANVAS_GROUP_MODE_DISABLED" value="0" enum="CanvasGroupMode">
</constant>
<constant name="CANVAS_GROUP_MODE_OPAQUE" value="1" enum="CanvasGroupMode">
<constant name="CANVAS_GROUP_MODE_CLIP_ONLY" value="1" enum="CanvasGroupMode">
</constant>
<constant name="CANVAS_GROUP_MODE_TRANSPARENT" value="2" enum="CanvasGroupMode">
<constant name="CANVAS_GROUP_MODE_CLIP_AND_DRAW" value="2" enum="CanvasGroupMode">
</constant>
<constant name="CANVAS_GROUP_MODE_TRANSPARENT" value="3" enum="CanvasGroupMode">
</constant>
<constant name="CANVAS_LIGHT_MODE_POINT" value="0" enum="CanvasLightMode">
</constant>
Expand Down
45 changes: 39 additions & 6 deletions drivers/gles3/rasterizer_canvas_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -433,10 +433,12 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, starting_index, false);
item_count = 0;

Rect2i group_rect = ci->canvas_group_owner->global_rect_cache;

if (ci->canvas_group_owner->canvas_group->mode == RS::CANVAS_GROUP_MODE_OPAQUE) {
if (ci->canvas_group_owner->canvas_group->mode != RS::CANVAS_GROUP_MODE_TRANSPARENT) {
Rect2i group_rect = ci->canvas_group_owner->global_rect_cache;
texture_storage->render_target_copy_to_back_buffer(p_to_render_target, group_rect, false);
if (ci->canvas_group_owner->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_AND_DRAW) {
items[item_count++] = ci->canvas_group_owner;
}
} else if (!backbuffer_cleared) {
texture_storage->render_target_clear_back_buffer(p_to_render_target, Rect2i(), Color(0, 0, 0, 0));
backbuffer_cleared = true;
Expand Down Expand Up @@ -544,9 +546,18 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
}

RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material;

if (material.is_null() && ci->canvas_group != nullptr) {
material = default_canvas_group_material;
if (ci->canvas_group != nullptr) {
if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_AND_DRAW) {
if (!p_to_backbuffer) {
material = default_clip_children_material;
}
} else {
if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_ONLY) {
material = default_clip_children_material;
} else {
material = default_canvas_group_material;
}
}
}

GLES3::CanvasShaderData *shader_data_cache = nullptr;
Expand Down Expand Up @@ -2074,6 +2085,26 @@ void fragment() {
material_storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader);
}

{
default_clip_children_shader = material_storage->shader_allocate();
material_storage->shader_initialize(default_clip_children_shader);

material_storage->shader_set_code(default_clip_children_shader, R"(
// Default clip children shader.

shader_type canvas_item;

void fragment() {
Comment on lines +2093 to +2097
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have separation lines here but not in RendererRD, maybe should be harmonized.

vec4 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0);
COLOR.rgb = c.rgb;
}
)");
default_clip_children_material = material_storage->material_allocate();
material_storage->material_initialize(default_clip_children_material);

material_storage->material_set_shader(default_clip_children_material, default_clip_children_shader);
}

default_canvas_texture = texture_storage->canvas_texture_allocate();
texture_storage->canvas_texture_initialize(default_canvas_texture);

Expand All @@ -2086,6 +2117,8 @@ RasterizerCanvasGLES3::~RasterizerCanvasGLES3() {
material_storage->shaders.canvas_shader.version_free(data.canvas_shader_default_version);
material_storage->material_free(default_canvas_group_material);
material_storage->shader_free(default_canvas_group_shader);
material_storage->material_free(default_clip_children_material);
material_storage->shader_free(default_clip_children_shader);
singleton = nullptr;

glDeleteBuffers(1, &data.canvas_quad_vertices);
Expand Down
2 changes: 2 additions & 0 deletions drivers/gles3/rasterizer_canvas_gles3.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,8 @@ class RasterizerCanvasGLES3 : public RendererCanvasRender {
RID default_canvas_texture;
RID default_canvas_group_material;
RID default_canvas_group_shader;
RID default_clip_children_material;
RID default_clip_children_shader;

typedef void Texture;

Expand Down
26 changes: 17 additions & 9 deletions scene/main/canvas_item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -986,8 +986,8 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_texture_repeat", "mode"), &CanvasItem::set_texture_repeat);
ClassDB::bind_method(D_METHOD("get_texture_repeat"), &CanvasItem::get_texture_repeat);

ClassDB::bind_method(D_METHOD("set_clip_children", "enable"), &CanvasItem::set_clip_children);
ClassDB::bind_method(D_METHOD("is_clipping_children"), &CanvasItem::is_clipping_children);
ClassDB::bind_method(D_METHOD("set_clip_children_mode", "mode"), &CanvasItem::set_clip_children_mode);
ClassDB::bind_method(D_METHOD("get_clip_children_mode"), &CanvasItem::get_clip_children_mode);

GDVIRTUAL_BIND(_draw);

Expand All @@ -997,7 +997,7 @@ void CanvasItem::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "self_modulate"), "set_self_modulate", "get_self_modulate");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_behind_parent"), "set_draw_behind_parent", "is_draw_behind_parent_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "top_level"), "set_as_top_level", "is_set_as_top_level");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_children"), "set_clip_children", "is_clipping_children");
ADD_PROPERTY(PropertyInfo(Variant::INT, "clip_children", PROPERTY_HINT_ENUM, "Disabled,Clip Only, Clip + Draw"), "set_clip_children_mode", "get_clip_children_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_light_mask", "get_light_mask");

ADD_GROUP("Texture", "texture_");
Expand Down Expand Up @@ -1035,6 +1035,11 @@ void CanvasItem::_bind_methods() {
BIND_ENUM_CONSTANT(TEXTURE_REPEAT_ENABLED);
BIND_ENUM_CONSTANT(TEXTURE_REPEAT_MIRROR);
BIND_ENUM_CONSTANT(TEXTURE_REPEAT_MAX);

BIND_ENUM_CONSTANT(CLIP_CHILDREN_DISABLED);
BIND_ENUM_CONSTANT(CLIP_CHILDREN_ONLY);
BIND_ENUM_CONSTANT(CLIP_CHILDREN_AND_DRAW);
BIND_ENUM_CONSTANT(CLIP_CHILDREN_MAX);
}

Transform2D CanvasItem::get_canvas_transform() const {
Expand Down Expand Up @@ -1169,20 +1174,23 @@ void CanvasItem::set_texture_repeat(TextureRepeat p_texture_repeat) {
notify_property_list_changed();
}

void CanvasItem::set_clip_children(bool p_enabled) {
if (clip_children == p_enabled) {
void CanvasItem::set_clip_children_mode(ClipChildrenMode p_clip_mode) {
ERR_FAIL_COND(p_clip_mode >= CLIP_CHILDREN_MAX);

if (clip_children_mode == p_clip_mode) {
return;
}
clip_children = p_enabled;
clip_children_mode = p_clip_mode;

if (Object::cast_to<CanvasGroup>(this) != nullptr) {
//avoid accidental bugs, make this not work on CanvasGroup
return;
}
RS::get_singleton()->canvas_item_set_canvas_group_mode(get_canvas_item(), clip_children ? RS::CANVAS_GROUP_MODE_OPAQUE : RS::CANVAS_GROUP_MODE_DISABLED);

RS::get_singleton()->canvas_item_set_canvas_group_mode(get_canvas_item(), RS::CanvasGroupMode(clip_children_mode));
}
bool CanvasItem::is_clipping_children() const {
return clip_children;
CanvasItem::ClipChildrenMode CanvasItem::get_clip_children_mode() const {
return clip_children_mode;
}

CanvasItem::TextureRepeat CanvasItem::get_texture_repeat() const {
Expand Down
18 changes: 14 additions & 4 deletions scene/main/canvas_item.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,16 @@ class CanvasItem : public Node {
TEXTURE_REPEAT_MAX,
};

enum ClipChildrenMode {
CLIP_CHILDREN_DISABLED,
CLIP_CHILDREN_ONLY,
CLIP_CHILDREN_AND_DRAW,
CLIP_CHILDREN_MAX,
};

private:
mutable SelfList<Node> xform_change;
mutable SelfList<Node>
xform_change;

RID canvas_item;
StringName canvas_group;
Expand All @@ -85,7 +93,6 @@ class CanvasItem : public Node {
Window *window = nullptr;
bool visible = true;
bool parent_visible_in_tree = false;
bool clip_children = false;
bool pending_update = false;
bool top_level = false;
bool drawing = false;
Expand All @@ -95,6 +102,8 @@ class CanvasItem : public Node {
bool notify_local_transform = false;
bool notify_transform = false;

ClipChildrenMode clip_children_mode = CLIP_CHILDREN_DISABLED;

RS::CanvasItemTextureFilter texture_filter_cache = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR;
RS::CanvasItemTextureRepeat texture_repeat_cache = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
TextureFilter texture_filter = TEXTURE_FILTER_PARENT_NODE;
Expand Down Expand Up @@ -200,8 +209,8 @@ class CanvasItem : public Node {
void queue_redraw();
void move_to_front();

void set_clip_children(bool p_enabled);
bool is_clipping_children() const;
void set_clip_children_mode(ClipChildrenMode p_clip_mode);
ClipChildrenMode get_clip_children_mode() const;

virtual void set_light_mask(int p_light_mask);
int get_light_mask() const;
Expand Down Expand Up @@ -321,6 +330,7 @@ class CanvasItem : public Node {

VARIANT_ENUM_CAST(CanvasItem::TextureFilter)
VARIANT_ENUM_CAST(CanvasItem::TextureRepeat)
VARIANT_ENUM_CAST(CanvasItem::ClipChildrenMode)

class CanvasTexture : public Texture2D {
GDCLASS(CanvasTexture, Texture2D);
Expand Down
4 changes: 2 additions & 2 deletions servers/rendering/renderer_rd/effects/copy_effects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,8 @@ void CopyEffects::copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, cons
copy.push_constant.flags |= COPY_FLAG_ALPHA_TO_ONE;
}

copy.push_constant.section[0] = 0;
copy.push_constant.section[1] = 0;
copy.push_constant.section[0] = p_rect.position.x;
copy.push_constant.section[1] = p_rect.position.y;
copy.push_constant.section[2] = p_rect.size.width;
copy.push_constant.section[3] = p_rect.size.height;
copy.push_constant.target[0] = p_rect.position.x;
Expand Down
47 changes: 42 additions & 5 deletions servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1111,8 +1111,20 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co

RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material;

if (material.is_null() && ci->canvas_group != nullptr) {
material = default_canvas_group_material;
if (ci->canvas_group != nullptr) {
if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_AND_DRAW) {
if (!p_to_backbuffer) {
material = default_clip_children_material;
}
} else {
if (material.is_null()) {
if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_ONLY) {
material = default_clip_children_material;
} else {
material = default_canvas_group_material;
}
}
}
}

if (material != prev_material) {
Expand Down Expand Up @@ -1437,10 +1449,12 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
item_count = 0;

Rect2i group_rect = ci->canvas_group_owner->global_rect_cache;

if (ci->canvas_group_owner->canvas_group->mode == RS::CANVAS_GROUP_MODE_OPAQUE) {
if (ci->canvas_group_owner->canvas_group->mode != RS::CANVAS_GROUP_MODE_TRANSPARENT) {
Rect2i group_rect = ci->canvas_group_owner->global_rect_cache;
texture_storage->render_target_copy_to_back_buffer(p_to_render_target, group_rect, false);
if (ci->canvas_group_owner->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_AND_DRAW) {
items[item_count++] = ci->canvas_group_owner;
}
} else if (!backbuffer_cleared) {
texture_storage->render_target_clear_back_buffer(p_to_render_target, Rect2i(), Color(0, 0, 0, 0));
backbuffer_cleared = true;
Expand Down Expand Up @@ -2738,6 +2752,26 @@ void fragment() {
material_storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader);
}

{
default_clip_children_shader = material_storage->shader_allocate();
material_storage->shader_initialize(default_clip_children_shader);

material_storage->shader_set_code(default_clip_children_shader, R"(
// Default clip children shader.

shader_type canvas_item;

void fragment() {
vec4 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0);
COLOR.rgb = c.rgb;
}
)");
default_clip_children_material = material_storage->material_allocate();
material_storage->material_initialize(default_clip_children_material);

material_storage->material_set_shader(default_clip_children_material, default_clip_children_shader);
}

static_assert(sizeof(PushConstant) == 128);
}

Expand Down Expand Up @@ -2789,6 +2823,9 @@ RendererCanvasRenderRD::~RendererCanvasRenderRD() {
material_storage->material_free(default_canvas_group_material);
material_storage->shader_free(default_canvas_group_shader);

material_storage->material_free(default_clip_children_material);
material_storage->shader_free(default_clip_children_shader);

{
if (state.canvas_state_buffer.is_valid()) {
RD::get_singleton()->free(state.canvas_state_buffer);
Expand Down
2 changes: 2 additions & 0 deletions servers/rendering/renderer_rd/renderer_canvas_render_rd.h
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender {

RID default_canvas_group_shader;
RID default_canvas_group_material;
RID default_clip_children_material;
RID default_clip_children_shader;

RS::CanvasItemTextureFilter default_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR;
RS::CanvasItemTextureRepeat default_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
Expand Down
3 changes: 2 additions & 1 deletion servers/rendering_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2636,7 +2636,8 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_REPEAT_MAX);

BIND_ENUM_CONSTANT(CANVAS_GROUP_MODE_DISABLED);
BIND_ENUM_CONSTANT(CANVAS_GROUP_MODE_OPAQUE);
BIND_ENUM_CONSTANT(CANVAS_GROUP_MODE_CLIP_ONLY);
BIND_ENUM_CONSTANT(CANVAS_GROUP_MODE_CLIP_AND_DRAW);
BIND_ENUM_CONSTANT(CANVAS_GROUP_MODE_TRANSPARENT);

/* CANVAS LIGHT */
Expand Down
3 changes: 2 additions & 1 deletion servers/rendering_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -1367,7 +1367,8 @@ class RenderingServer : public Object {

enum CanvasGroupMode {
CANVAS_GROUP_MODE_DISABLED,
CANVAS_GROUP_MODE_OPAQUE,
CANVAS_GROUP_MODE_CLIP_ONLY,
CANVAS_GROUP_MODE_CLIP_AND_DRAW,
CANVAS_GROUP_MODE_TRANSPARENT,
};

Expand Down