diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 2f7e68e463f..522685bf87d 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -396,6 +396,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_ Item *ci = p_item_list; Item *canvas_group_owner = nullptr; + bool skip_item = false; 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; 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) { + ci->canvas_group_owner->use_canvas_group = false; items[item_count++] = ci->canvas_group_owner; } } 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 } - if (!backbuffer_cleared && canvas_group_owner == nullptr && ci->canvas_group != nullptr && !backbuffer_copy) { - texture_storage->render_target_clear_back_buffer(p_to_render_target, Rect2i(), Color(0, 0, 0, 0)); - backbuffer_cleared = true; + if (canvas_group_owner == nullptr && ci->canvas_group != nullptr && ci->canvas_group->mode != RS::CANVAS_GROUP_MODE_CLIP_AND_DRAW) { + skip_item = true; } 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; // Backbuffer is dirty now and needs to be re-cleared if another CanvasGroup needs it. 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) { @@ -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); 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_mipmaps_cached = backbuffer_gen_mipmaps; + backbuffer_gen_mipmaps = false; } 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 - 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 (update_skeletons) { mesh_storage->update_mesh_instances(); 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 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; - if (ci->canvas_group != nullptr) { + if (ci->use_canvas_group) { 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 { if (material.is_null()) { if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_ONLY) { diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h index dc838047ccc..c30e53c29e7 100644 --- a/servers/rendering/renderer_canvas_render.h +++ b/servers/rendering/renderer_canvas_render.h @@ -321,6 +321,7 @@ public: }; CanvasGroup *canvas_group = nullptr; + bool use_canvas_group = false; int light_mask; int z_final; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 78bdd3f5411..f49d8be37a0 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -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; - if (ci->canvas_group != nullptr) { + if (ci->use_canvas_group) { 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 { if (material.is_null()) { 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; Item *canvas_group_owner = nullptr; + bool skip_item = false; bool update_skeletons = 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; 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) { + ci->canvas_group_owner->use_canvas_group = false; items[item_count++] = ci->canvas_group_owner; } } 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 } - if (!backbuffer_cleared && canvas_group_owner == nullptr && ci->canvas_group != nullptr && !backbuffer_copy) { - texture_storage->render_target_clear_back_buffer(p_to_render_target, Rect2i(), Color(0, 0, 0, 0)); - backbuffer_cleared = true; + if (canvas_group_owner == nullptr && ci->canvas_group != nullptr && ci->canvas_group->mode != RS::CANVAS_GROUP_MODE_CLIP_AND_DRAW) { + skip_item = true; } 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; // Backbuffer is dirty now and needs to be re-cleared if another CanvasGroup needs it. 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) { @@ -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); 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_mipmaps_cached = backbuffer_gen_mipmaps; + backbuffer_gen_mipmaps = false; } 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; } - 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 (update_skeletons) { @@ -1523,7 +1531,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p 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 item_count = 0; }