diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index 3b91bace7e1..42ba93c0f2e 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -107,50 +107,57 @@ void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas } } -void RendererCanvasCull::_collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, RendererCanvasCull::Item *p_material_owner, const Color &p_modulate, RendererCanvasCull::Item **r_items, int &r_index, int p_z) { +void RendererCanvasCull::_collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, RendererCanvasCull::Item *p_material_owner, const Color &p_modulate, RendererCanvasCull::Item **r_items, int &r_index, int &r_ysort_children_count, int p_z, uint32_t p_canvas_cull_mask) { int child_item_count = p_canvas_item->child_items.size(); RendererCanvasCull::Item **child_items = p_canvas_item->child_items.ptrw(); for (int i = 0; i < child_item_count; i++) { if (child_items[i]->visible) { - // To y-sort according to the item's final position, physics interpolation - // and transform snapping need to be applied before y-sorting. - Transform2D child_xform; - if (!_interpolation_data.interpolation_enabled || !child_items[i]->interpolated) { - child_xform = child_items[i]->xform_curr; + if (child_items[i]->visibility_layer & p_canvas_cull_mask) { + // To y-sort according to the item's final position, physics interpolation + // and transform snapping need to be applied before y-sorting. + Transform2D child_xform; + if (!_interpolation_data.interpolation_enabled || !child_items[i]->interpolated) { + child_xform = child_items[i]->xform_curr; + } else { + real_t f = Engine::get_singleton()->get_physics_interpolation_fraction(); + TransformInterpolator::interpolate_transform_2d(child_items[i]->xform_prev, child_items[i]->xform_curr, child_xform, f); + } + + if (snapping_2d_transforms_to_pixel) { + child_xform.columns[2] = (child_xform.columns[2] + Point2(0.5, 0.5)).floor(); + } + + r_items[r_index] = child_items[i]; + child_items[i]->ysort_xform = p_canvas_item->ysort_xform * child_xform; + child_items[i]->material_owner = child_items[i]->use_parent_material ? p_material_owner : nullptr; + child_items[i]->ysort_modulate = p_modulate; + child_items[i]->ysort_index = r_index; + child_items[i]->ysort_parent_abs_z_index = p_z; + + if (!child_items[i]->repeat_source) { + child_items[i]->repeat_size = p_canvas_item->repeat_size; + child_items[i]->repeat_times = p_canvas_item->repeat_times; + child_items[i]->repeat_source_item = p_canvas_item->repeat_source_item; + } + + // Y sorted canvas items are flattened into r_items. Calculate their absolute z index to use when rendering r_items. + int abs_z = 0; + if (child_items[i]->z_relative) { + abs_z = CLAMP(p_z + child_items[i]->z_index, RS::CANVAS_ITEM_Z_MIN, RS::CANVAS_ITEM_Z_MAX); + } else { + abs_z = child_items[i]->z_index; + } + + r_index++; + + if (child_items[i]->sort_y) { + _collect_ysort_children(child_items[i], child_items[i]->use_parent_material ? p_material_owner : child_items[i], p_modulate * child_items[i]->modulate, r_items, r_index, r_ysort_children_count, abs_z, p_canvas_cull_mask); + } } else { - real_t f = Engine::get_singleton()->get_physics_interpolation_fraction(); - TransformInterpolator::interpolate_transform_2d(child_items[i]->xform_prev, child_items[i]->xform_curr, child_xform, f); - } - - if (snapping_2d_transforms_to_pixel) { - child_xform.columns[2] = (child_xform.columns[2] + Point2(0.5, 0.5)).floor(); - } - - r_items[r_index] = child_items[i]; - child_items[i]->ysort_xform = p_canvas_item->ysort_xform * child_xform; - child_items[i]->material_owner = child_items[i]->use_parent_material ? p_material_owner : nullptr; - child_items[i]->ysort_modulate = p_modulate; - child_items[i]->ysort_index = r_index; - child_items[i]->ysort_parent_abs_z_index = p_z; - - if (!child_items[i]->repeat_source) { - child_items[i]->repeat_size = p_canvas_item->repeat_size; - child_items[i]->repeat_times = p_canvas_item->repeat_times; - child_items[i]->repeat_source_item = p_canvas_item->repeat_source_item; - } - - // Y sorted canvas items are flattened into r_items. Calculate their absolute z index to use when rendering r_items. - int abs_z = 0; - if (child_items[i]->z_relative) { - abs_z = CLAMP(p_z + child_items[i]->z_index, RS::CANVAS_ITEM_Z_MIN, RS::CANVAS_ITEM_Z_MAX); - } else { - abs_z = child_items[i]->z_index; - } - - r_index++; - - if (child_items[i]->sort_y) { - _collect_ysort_children(child_items[i], child_items[i]->use_parent_material ? p_material_owner : child_items[i], p_modulate * child_items[i]->modulate, r_items, r_index, abs_z); + r_ysort_children_count--; + if (child_items[i]->sort_y) { + r_ysort_children_count -= child_items[i]->ysort_children_count; + } } } } @@ -164,7 +171,10 @@ int RendererCanvasCull::_count_ysort_children(RendererCanvasCull::Item *p_canvas if (child_items[i]->visible) { ysort_children_count++; if (child_items[i]->sort_y) { - ysort_children_count += _count_ysort_children(child_items[i]); + if (child_items[i]->ysort_children_count == -1) { + child_items[i]->ysort_children_count = _count_ysort_children(child_items[i]); + } + ysort_children_count += child_items[i]->ysort_children_count; } } } @@ -439,7 +449,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 ci->ysort_parent_abs_z_index = parent_z; child_items[0] = ci; int i = 1; - _collect_ysort_children(ci, p_material_owner, Color(1, 1, 1, 1), child_items, i, p_z); + _collect_ysort_children(ci, p_material_owner, Color(1, 1, 1, 1), child_items, i, child_item_count, p_z, p_canvas_cull_mask); SortArray sorter; sorter.sort(child_items, child_item_count); diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h index 1f01bbce11a..c83fa1fb66e 100644 --- a/servers/rendering/renderer_canvas_cull.h +++ b/servers/rendering/renderer_canvas_cull.h @@ -207,7 +207,7 @@ private: void _render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t p_canvas_cull_mask, RenderingMethod::RenderInfo *r_render_info = nullptr); void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_parent_xform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool p_is_already_y_sorted, uint32_t p_canvas_cull_mask, const Point2 &p_repeat_size, int p_repeat_times, RendererCanvasRender::Item *p_repeat_source_item); - void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, RendererCanvasCull::Item *p_material_owner, const Color &p_modulate, RendererCanvasCull::Item **r_items, int &r_index, int p_z); + void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, RendererCanvasCull::Item *p_material_owner, const Color &p_modulate, RendererCanvasCull::Item **r_items, int &r_index, int &r_ysort_children_count, int p_z, uint32_t p_canvas_cull_mask); int _count_ysort_children(RendererCanvasCull::Item *p_canvas_item); void _mark_ysort_dirty(RendererCanvasCull::Item *ysort_owner);