Fixes a canvas item set to clip children being drawn as black if no children are visible

This commit is contained in:
SlugFiller 2023-03-07 08:09:39 +02:00
parent d857005f5f
commit f25508befb
3 changed files with 37 additions and 20 deletions

View file

@ -396,6 +396,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
Item *ci = p_item_list; Item *ci = p_item_list;
Item *canvas_group_owner = nullptr; Item *canvas_group_owner = nullptr;
bool skip_item = false;
state.last_item_index = 0; state.last_item_index = 0;
@ -464,6 +465,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
Rect2i group_rect = ci->canvas_group_owner->global_rect_cache; 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); 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) { if (ci->canvas_group_owner->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_AND_DRAW) {
ci->canvas_group_owner->use_canvas_group = false;
items[item_count++] = ci->canvas_group_owner; items[item_count++] = ci->canvas_group_owner;
} }
} else if (!backbuffer_cleared) { } else if (!backbuffer_cleared) {
@ -478,9 +480,8 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
ci->canvas_group_owner = nullptr; //must be cleared ci->canvas_group_owner = nullptr; //must be cleared
} }
if (!backbuffer_cleared && canvas_group_owner == nullptr && ci->canvas_group != nullptr && !backbuffer_copy) { if (canvas_group_owner == nullptr && ci->canvas_group != nullptr && ci->canvas_group->mode != RS::CANVAS_GROUP_MODE_CLIP_AND_DRAW) {
texture_storage->render_target_clear_back_buffer(p_to_render_target, Rect2i(), Color(0, 0, 0, 0)); skip_item = true;
backbuffer_cleared = true;
} }
if (ci == canvas_group_owner) { if (ci == canvas_group_owner) {
@ -498,6 +499,11 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
canvas_group_owner = nullptr; canvas_group_owner = nullptr;
// Backbuffer is dirty now and needs to be re-cleared if another CanvasGroup needs it. // Backbuffer is dirty now and needs to be re-cleared if another CanvasGroup needs it.
backbuffer_cleared = false; backbuffer_cleared = false;
// Tell the renderer to paint this as a canvas group
ci->use_canvas_group = true;
} else {
ci->use_canvas_group = false;
} }
if (backbuffer_copy) { if (backbuffer_copy) {
@ -513,9 +519,9 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, backbuffer_gen_mipmaps); texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, backbuffer_gen_mipmaps);
backbuffer_copy = false; backbuffer_copy = false;
backbuffer_gen_mipmaps = false;
material_screen_texture_cached = true; // After a backbuffer copy, screen texture makes no further copies. material_screen_texture_cached = true; // After a backbuffer copy, screen texture makes no further copies.
material_screen_texture_mipmaps_cached = backbuffer_gen_mipmaps; material_screen_texture_mipmaps_cached = backbuffer_gen_mipmaps;
backbuffer_gen_mipmaps = false;
} }
if (backbuffer_gen_mipmaps) { if (backbuffer_gen_mipmaps) {
@ -526,14 +532,18 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
} }
// just add all items for now // just add all items for now
items[item_count++] = ci; if (skip_item) {
skip_item = false;
} else {
items[item_count++] = ci;
}
if (!ci->next || item_count == MAX_RENDER_ITEMS - 1) { if (!ci->next || item_count == MAX_RENDER_ITEMS - 1) {
if (update_skeletons) { if (update_skeletons) {
mesh_storage->update_mesh_instances(); mesh_storage->update_mesh_instances();
update_skeletons = false; update_skeletons = false;
} }
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used); _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used, canvas_group_owner != nullptr);
//then reset //then reset
item_count = 0; item_count = 0;
} }
@ -586,11 +596,9 @@ 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; RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material;
if (ci->canvas_group != nullptr) { if (ci->use_canvas_group) {
if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_AND_DRAW) { if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_AND_DRAW) {
if (!p_to_backbuffer) { material = default_clip_children_material;
material = default_clip_children_material;
}
} else { } else {
if (material.is_null()) { if (material.is_null()) {
if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_ONLY) { if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_ONLY) {

View file

@ -321,6 +321,7 @@ public:
}; };
CanvasGroup *canvas_group = nullptr; CanvasGroup *canvas_group = nullptr;
bool use_canvas_group = false;
int light_mask; int light_mask;
int z_final; int z_final;

View file

@ -1110,11 +1110,9 @@ 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; RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material;
if (ci->canvas_group != nullptr) { if (ci->use_canvas_group) {
if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_AND_DRAW) { if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_AND_DRAW) {
if (!p_to_backbuffer) { material = default_clip_children_material;
material = default_clip_children_material;
}
} else { } else {
if (material.is_null()) { if (material.is_null()) {
if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_ONLY) { if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_ONLY) {
@ -1381,6 +1379,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
bool backbuffer_gen_mipmaps = false; bool backbuffer_gen_mipmaps = false;
Item *canvas_group_owner = nullptr; Item *canvas_group_owner = nullptr;
bool skip_item = false;
bool update_skeletons = false; bool update_skeletons = false;
bool time_used = false; bool time_used = false;
@ -1453,6 +1452,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
Rect2i group_rect = ci->canvas_group_owner->global_rect_cache; 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); 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) { if (ci->canvas_group_owner->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_AND_DRAW) {
ci->canvas_group_owner->use_canvas_group = false;
items[item_count++] = ci->canvas_group_owner; items[item_count++] = ci->canvas_group_owner;
} }
} else if (!backbuffer_cleared) { } else if (!backbuffer_cleared) {
@ -1467,9 +1467,8 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
ci->canvas_group_owner = nullptr; //must be cleared ci->canvas_group_owner = nullptr; //must be cleared
} }
if (!backbuffer_cleared && canvas_group_owner == nullptr && ci->canvas_group != nullptr && !backbuffer_copy) { if (canvas_group_owner == nullptr && ci->canvas_group != nullptr && ci->canvas_group->mode != RS::CANVAS_GROUP_MODE_CLIP_AND_DRAW) {
texture_storage->render_target_clear_back_buffer(p_to_render_target, Rect2i(), Color(0, 0, 0, 0)); skip_item = true;
backbuffer_cleared = true;
} }
if (ci == canvas_group_owner) { if (ci == canvas_group_owner) {
@ -1488,6 +1487,11 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
canvas_group_owner = nullptr; canvas_group_owner = nullptr;
// Backbuffer is dirty now and needs to be re-cleared if another CanvasGroup needs it. // Backbuffer is dirty now and needs to be re-cleared if another CanvasGroup needs it.
backbuffer_cleared = false; backbuffer_cleared = false;
// Tell the renderer to paint this as a canvas group
ci->use_canvas_group = true;
} else {
ci->use_canvas_group = false;
} }
if (backbuffer_copy) { if (backbuffer_copy) {
@ -1503,9 +1507,9 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, backbuffer_gen_mipmaps); texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, backbuffer_gen_mipmaps);
backbuffer_copy = false; backbuffer_copy = false;
backbuffer_gen_mipmaps = false;
material_screen_texture_cached = true; // After a backbuffer copy, screen texture makes no further copies. material_screen_texture_cached = true; // After a backbuffer copy, screen texture makes no further copies.
material_screen_texture_mipmaps_cached = backbuffer_gen_mipmaps; material_screen_texture_mipmaps_cached = backbuffer_gen_mipmaps;
backbuffer_gen_mipmaps = false;
} }
if (backbuffer_gen_mipmaps) { if (backbuffer_gen_mipmaps) {
@ -1515,7 +1519,11 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
material_screen_texture_mipmaps_cached = true; material_screen_texture_mipmaps_cached = true;
} }
items[item_count++] = ci; if (skip_item) {
skip_item = false;
} else {
items[item_count++] = ci;
}
if (!ci->next || item_count == MAX_RENDER_ITEMS - 1) { if (!ci->next || item_count == MAX_RENDER_ITEMS - 1) {
if (update_skeletons) { if (update_skeletons) {
@ -1523,7 +1531,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
update_skeletons = false; update_skeletons = false;
} }
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used, false); _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used, canvas_group_owner != nullptr);
//then reset //then reset
item_count = 0; item_count = 0;
} }