Viewport canvas cull mask feature

Co-authored-by: Valentin Zagura <puthre@gmail.com>
This commit is contained in:
BimDav 2021-09-02 20:07:04 +02:00 committed by BimDav
parent 11e1bac768
commit fcb9be66a2
14 changed files with 186 additions and 22 deletions

View file

@ -456,6 +456,13 @@
Returns this item's transform in relation to the viewport.
</description>
</method>
<method name="get_visibility_layer_bit" qualifiers="const">
<return type="bool" />
<param index="0" name="layer" type="int" />
<description>
Returns an individual bit on the rendering visibility layer.
</description>
</method>
<method name="get_world_2d" qualifiers="const">
<return type="World2D" />
<description>
@ -527,6 +534,14 @@
If [param enable] is [code]true[/code], this node will receive [constant NOTIFICATION_TRANSFORM_CHANGED] when its global transform changes.
</description>
</method>
<method name="set_visibility_layer_bit">
<return type="void" />
<param index="0" name="layer" type="int" />
<param index="1" name="enabled" type="bool" />
<description>
Set/clear individual bits on the rendering visibility layer. This simplifies editing this [CanvasItem]'s visibility layer.
</description>
</method>
<method name="show">
<return type="void" />
<description>
@ -565,6 +580,9 @@
<member name="use_parent_material" type="bool" setter="set_use_parent_material" getter="get_use_parent_material" default="false">
If [code]true[/code], the parent [CanvasItem]'s [member material] property is used as this one's material.
</member>
<member name="visibility_layer" type="int" setter="set_visibility_layer" getter="get_visibility_layer" default="1">
The rendering layer in which this [CanvasItem] is rendered by [Viewport] nodes. A [Viewport] will render a [CanvasItem] if it and all its parents share a layer with the [Viewport]'s canvas cull mask.
</member>
<member name="visible" type="bool" setter="set_visible" getter="is_visible" default="true">
If [code]true[/code], this [CanvasItem] is drawn. The node is only visible if all of its antecedents are visible as well (in other words, [method is_visible_in_tree] must return [code]true[/code]).
[b]Note:[/b] For controls that inherit [Popup], the correct way to make them visible is to call one of the multiple [code]popup*()[/code] functions instead.

View file

@ -498,6 +498,14 @@
Sets if the [CanvasItem] uses its parent's material.
</description>
</method>
<method name="canvas_item_set_visibility_layer">
<return type="void" />
<param index="0" name="item" type="RID" />
<param index="1" name="visibility_layer" type="int" />
<description>
Sets the rendering visibility layer associated with this [CanvasItem]. Only [Viewport] nodes with a matching rendering mask will render this [CanvasItem].
</description>
</method>
<method name="canvas_item_set_visibility_notifier">
<return type="void" />
<param index="0" name="item" type="RID" />
@ -3142,6 +3150,14 @@
If [code]true[/code], sets the viewport active, else sets it inactive.
</description>
</method>
<method name="viewport_set_canvas_cull_mask">
<return type="void" />
<param index="0" name="viewport" type="RID" />
<param index="1" name="canvas_cull_mask" type="int" />
<description>
Sets the rendering mask associated with this [Viewport]. Only [CanvasItem] nodes with a matching rendering visibility layer will be rendered by this [Viewport].
</description>
</method>
<method name="viewport_set_canvas_stacking">
<return type="void" />
<param index="0" name="viewport" type="RID" />

View file

@ -45,6 +45,13 @@
Returns the currently active 3D camera.
</description>
</method>
<method name="get_canvas_cull_mask_bit" qualifiers="const">
<return type="bool" />
<param index="0" name="layer" type="int" />
<description>
Returns an individual bit on the rendering layer mask.
</description>
</method>
<method name="get_final_transform" qualifiers="const">
<return type="Transform2D" />
<description>
@ -176,6 +183,14 @@
If none of the methods handle the event and [member physics_object_picking] is [code]true[/code], the event is used for physics object picking.
</description>
</method>
<method name="set_canvas_cull_mask_bit">
<return type="void" />
<param index="0" name="layer" type="int" />
<param index="1" name="enable" type="bool" />
<description>
Set/clear individual bits on the rendering layer mask. This simplifies editing this [Viewport]'s layers.
</description>
</method>
<method name="set_input_as_handled">
<return type="void" />
<description>
@ -205,6 +220,9 @@
<member name="audio_listener_enable_3d" type="bool" setter="set_as_audio_listener_3d" getter="is_audio_listener_3d" default="false">
If [code]true[/code], the viewport will process 3D audio streams.
</member>
<member name="canvas_cull_mask" type="int" setter="set_canvas_cull_mask" getter="get_canvas_cull_mask" default="4294967295">
The rendering layers in which this [Viewport] renders [CanvasItem] nodes.
</member>
<member name="canvas_item_default_texture_filter" type="int" setter="set_default_canvas_item_texture_filter" getter="get_default_canvas_item_texture_filter" enum="Viewport.DefaultCanvasItemTextureFilter" default="1">
Sets the default filter mode used by [CanvasItem]s in this Viewport. See [enum DefaultCanvasItemTextureFilter] for options.
</member>

View file

@ -222,6 +222,7 @@ void CanvasItem::_enter_canvas() {
}
RenderingServer::get_singleton()->canvas_item_set_parent(canvas_item, canvas);
RenderingServer::get_singleton()->canvas_item_set_visibility_layer(canvas_item, visibility_layer);
canvas_group = "root_canvas" + itos(canvas.get_id());
@ -239,6 +240,7 @@ void CanvasItem::_enter_canvas() {
canvas_layer = parent->canvas_layer;
RenderingServer::get_singleton()->canvas_item_set_parent(canvas_item, parent->get_canvas_item());
RenderingServer::get_singleton()->canvas_item_set_draw_index(canvas_item, get_index());
RenderingServer::get_singleton()->canvas_item_set_visibility_layer(canvas_item, visibility_layer);
}
pending_update = false;
@ -980,6 +982,11 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("make_canvas_position_local", "screen_point"), &CanvasItem::make_canvas_position_local);
ClassDB::bind_method(D_METHOD("make_input_local", "event"), &CanvasItem::make_input_local);
ClassDB::bind_method(D_METHOD("set_visibility_layer", "layer"), &CanvasItem::set_visibility_layer);
ClassDB::bind_method(D_METHOD("get_visibility_layer"), &CanvasItem::get_visibility_layer);
ClassDB::bind_method(D_METHOD("set_visibility_layer_bit", "layer", "enabled"), &CanvasItem::set_visibility_layer_bit);
ClassDB::bind_method(D_METHOD("get_visibility_layer_bit", "layer"), &CanvasItem::get_visibility_layer_bit);
ClassDB::bind_method(D_METHOD("set_texture_filter", "mode"), &CanvasItem::set_texture_filter);
ClassDB::bind_method(D_METHOD("get_texture_filter"), &CanvasItem::get_texture_filter);
@ -999,6 +1006,7 @@ void CanvasItem::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "top_level"), "set_as_top_level", "is_set_as_top_level");
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_PROPERTY(PropertyInfo(Variant::INT, "visibility_layer", PROPERTY_HINT_LAYERS_2D_RENDER), "set_visibility_layer", "get_visibility_layer");
ADD_GROUP("Texture", "texture_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Inherit,Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Anisotropic,Linear Mipmap Anisotropic"), "set_texture_filter", "get_texture_filter");
@ -1097,6 +1105,29 @@ int CanvasItem::get_canvas_layer() const {
}
}
void CanvasItem::set_visibility_layer(uint32_t p_visibility_layer) {
visibility_layer = p_visibility_layer;
RenderingServer::get_singleton()->canvas_item_set_visibility_layer(canvas_item, p_visibility_layer);
}
uint32_t CanvasItem::get_visibility_layer() const {
return visibility_layer;
}
void CanvasItem::set_visibility_layer_bit(uint32_t p_visibility_layer, bool p_enable) {
ERR_FAIL_INDEX(p_visibility_layer, 32);
if (p_enable) {
set_visibility_layer(visibility_layer | (1 << p_visibility_layer));
} else {
set_visibility_layer(visibility_layer & (~(1 << p_visibility_layer)));
}
}
bool CanvasItem::get_visibility_layer_bit(uint32_t p_visibility_layer) const {
ERR_FAIL_INDEX_V(p_visibility_layer, 32, false);
return (visibility_layer & (1 << p_visibility_layer));
}
void CanvasItem::_refresh_texture_filter_cache() {
if (!is_inside_tree()) {
return;

View file

@ -89,6 +89,7 @@ private:
List<CanvasItem *>::Element *C = nullptr;
int light_mask = 1;
uint32_t visibility_layer = 1;
Window *window = nullptr;
bool visible = true;
@ -223,6 +224,12 @@ public:
void set_self_modulate(const Color &p_self_modulate);
Color get_self_modulate() const;
void set_visibility_layer(uint32_t p_visibility_layer);
uint32_t get_visibility_layer() const;
void set_visibility_layer_bit(uint32_t p_visibility_layer, bool p_enable);
bool get_visibility_layer_bit(uint32_t p_visibility_layer) const;
/* DRAWING API */
void draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width = 1.0, real_t p_dash = 2.0);

View file

@ -362,6 +362,7 @@ void Viewport::_notification(int p_what) {
current_canvas = find_world_2d()->get_canvas();
RenderingServer::get_singleton()->viewport_attach_canvas(viewport, current_canvas);
RenderingServer::get_singleton()->viewport_set_canvas_cull_mask(viewport, canvas_cull_mask);
_update_audio_listener_2d();
#ifndef _3D_DISABLED
RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world_3d()->get_scenario());
@ -993,11 +994,6 @@ void Viewport::set_world_2d(const Ref<World2D> &p_world_2d) {
return;
}
if (parent && parent->find_world_2d() == p_world_2d) {
WARN_PRINT("Unable to use parent world_2d as world_2d");
return;
}
if (is_inside_tree()) {
RenderingServer::get_singleton()->viewport_remove_canvas(viewport, current_canvas);
}
@ -3244,6 +3240,29 @@ Transform2D Viewport::get_screen_transform() const {
return _get_input_pre_xform().affine_inverse() * get_final_transform();
}
void Viewport::set_canvas_cull_mask(uint32_t p_canvas_cull_mask) {
canvas_cull_mask = p_canvas_cull_mask;
RenderingServer::get_singleton()->viewport_set_canvas_cull_mask(viewport, canvas_cull_mask);
}
uint32_t Viewport::get_canvas_cull_mask() const {
return canvas_cull_mask;
}
void Viewport::set_canvas_cull_mask_bit(uint32_t p_layer, bool p_enable) {
ERR_FAIL_INDEX(p_layer, 32);
if (p_enable) {
set_canvas_cull_mask(canvas_cull_mask | (1 << p_layer));
} else {
set_canvas_cull_mask(canvas_cull_mask & (~(1 << p_layer)));
}
}
bool Viewport::get_canvas_cull_mask_bit(uint32_t p_layer) const {
ERR_FAIL_INDEX_V(p_layer, 32, false);
return (canvas_cull_mask & (1 << p_layer));
}
#ifndef _3D_DISABLED
AudioListener3D *Viewport::get_audio_listener_3d() const {
return audio_listener_3d;
@ -3815,6 +3834,12 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_embedding_subwindows", "enable"), &Viewport::set_embedding_subwindows);
ClassDB::bind_method(D_METHOD("is_embedding_subwindows"), &Viewport::is_embedding_subwindows);
ClassDB::bind_method(D_METHOD("set_canvas_cull_mask", "mask"), &Viewport::set_canvas_cull_mask);
ClassDB::bind_method(D_METHOD("get_canvas_cull_mask"), &Viewport::get_canvas_cull_mask);
ClassDB::bind_method(D_METHOD("set_canvas_cull_mask_bit", "layer", "enable"), &Viewport::set_canvas_cull_mask_bit);
ClassDB::bind_method(D_METHOD("get_canvas_cull_mask_bit", "layer"), &Viewport::get_canvas_cull_mask_bit);
ClassDB::bind_method(D_METHOD("set_default_canvas_item_texture_repeat", "mode"), &Viewport::set_default_canvas_item_texture_repeat);
ClassDB::bind_method(D_METHOD("get_default_canvas_item_texture_repeat"), &Viewport::get_default_canvas_item_texture_repeat);
@ -3920,6 +3945,7 @@ void Viewport::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::INT, "positional_shadow_atlas_quad_3", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_positional_shadow_atlas_quadrant_subdiv", "get_positional_shadow_atlas_quadrant_subdiv", 3);
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "canvas_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_canvas_transform", "get_canvas_transform");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "global_canvas_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_canvas_transform", "get_global_canvas_transform");
ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_cull_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_canvas_cull_mask", "get_canvas_cull_mask");
ADD_SIGNAL(MethodInfo("size_changed"));
ADD_SIGNAL(MethodInfo("gui_focus_changed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Control")));

View file

@ -317,6 +317,8 @@ private:
SDFOversize sdf_oversize = SDF_OVERSIZE_120_PERCENT;
SDFScale sdf_scale = SDF_SCALE_50_PERCENT;
uint32_t canvas_cull_mask = 0xffffffff; // by default show everything
enum SubWindowDrag {
SUB_WINDOW_DRAG_DISABLED,
SUB_WINDOW_DRAG_MOVE,
@ -639,6 +641,12 @@ public:
void pass_mouse_focus_to(Viewport *p_viewport, Control *p_control);
void set_canvas_cull_mask(uint32_t p_layers);
uint32_t get_canvas_cull_mask() const;
void set_canvas_cull_mask_bit(uint32_t p_layer, bool p_enable);
bool get_canvas_cull_mask_bit(uint32_t p_layer) const;
virtual Transform2D get_screen_transform() const;
#ifndef _3D_DISABLED

View file

@ -38,17 +38,17 @@
static const int z_range = RS::CANVAS_ITEM_Z_MAX - RS::CANVAS_ITEM_Z_MIN + 1;
void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel) {
void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t canvas_cull_mask) {
RENDER_TIMESTAMP("Cull CanvasItem Tree");
memset(z_list, 0, z_range * sizeof(RendererCanvasRender::Item *));
memset(z_last_list, 0, z_range * sizeof(RendererCanvasRender::Item *));
for (int i = 0; i < p_child_item_count; i++) {
_cull_canvas_item(p_child_items[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true);
_cull_canvas_item(p_child_items[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true, canvas_cull_mask);
}
if (p_canvas_item) {
_cull_canvas_item(p_canvas_item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true);
_cull_canvas_item(p_canvas_item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true, canvas_cull_mask);
}
RendererCanvasRender::Item *list = nullptr;
@ -223,13 +223,17 @@ void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item *
}
}
void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, 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 allow_y_sort) {
void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, 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 allow_y_sort, uint32_t canvas_cull_mask) {
Item *ci = p_canvas_item;
if (!ci->visible) {
return;
}
if (!(ci->visibility_layer & canvas_cull_mask)) {
return;
}
if (ci->children_order_dirty) {
ci->child_items.sort_custom<ItemIndexSort>();
ci->children_order_dirty = false;
@ -313,7 +317,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
sorter.sort(child_items, child_item_count);
for (i = 0; i < child_item_count; i++) {
_cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, child_items[i]->ysort_parent_abs_z_index, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner, false);
_cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, child_items[i]->ysort_parent_abs_z_index, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner, false, canvas_cull_mask);
}
} else {
RendererCanvasRender::Item *canvas_group_from = nullptr;
@ -337,19 +341,19 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
if (!child_items[i]->behind && !use_canvas_group) {
continue;
}
_cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true);
_cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true, canvas_cull_mask);
}
_attach_canvas_item_for_draw(ci, p_canvas_clip, r_z_list, r_z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from, xform);
for (int i = 0; i < child_item_count; i++) {
if (child_items[i]->behind || use_canvas_group) {
continue;
}
_cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true);
_cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true, canvas_cull_mask);
}
}
}
void RendererCanvasCull::render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, const Rect2 &p_clip_rect, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel) {
void RendererCanvasCull::render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, const Rect2 &p_clip_rect, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel, uint32_t canvas_cull_mask) {
RENDER_TIMESTAMP("> Render Canvas");
sdf_used = false;
@ -372,26 +376,26 @@ void RendererCanvasCull::render_canvas(RID p_render_target, Canvas *p_canvas, co
}
if (!has_mirror) {
_render_canvas_item_tree(p_render_target, ci, l, nullptr, p_transform, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel);
_render_canvas_item_tree(p_render_target, ci, l, nullptr, p_transform, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, canvas_cull_mask);
} else {
//used for parallaxlayer mirroring
for (int i = 0; i < l; i++) {
const Canvas::ChildItem &ci2 = p_canvas->child_items[i];
_render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, p_transform, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel);
_render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, p_transform, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, canvas_cull_mask);
//mirroring (useful for scrolling backgrounds)
if (ci2.mirror.x != 0) {
Transform2D xform2 = p_transform * Transform2D(0, Vector2(ci2.mirror.x, 0));
_render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel);
_render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, canvas_cull_mask);
}
if (ci2.mirror.y != 0) {
Transform2D xform2 = p_transform * Transform2D(0, Vector2(0, ci2.mirror.y));
_render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel);
_render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, canvas_cull_mask);
}
if (ci2.mirror.y != 0 && ci2.mirror.x != 0) {
Transform2D xform2 = p_transform * Transform2D(0, ci2.mirror);
_render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel);
_render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, canvas_cull_mask);
}
}
}
@ -513,6 +517,20 @@ void RendererCanvasCull::canvas_item_set_transform(RID p_item, const Transform2D
canvas_item->xform = p_transform;
}
void RendererCanvasCull::canvas_item_set_visibility_layer(RID p_item, uint32_t p_visibility_layer) {
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->visibility_layer = p_visibility_layer;
}
uint32_t RendererCanvasCull::canvas_item_get_visibility_layer(RID p_item) {
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
if (!canvas_item)
return 0;
return canvas_item->visibility_layer;
}
void RendererCanvasCull::canvas_item_set_clip(RID p_item, bool p_clip) {
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);

View file

@ -54,6 +54,7 @@ public:
Vector2 ysort_pos;
int ysort_index;
int ysort_parent_abs_z_index; // Absolute Z index of parent. Only populated and used when y-sorting.
uint32_t visibility_layer = 0xffffffff;
Vector<Item *> child_items;
@ -179,14 +180,14 @@ public:
_FORCE_INLINE_ void _attach_canvas_item_for_draw(Item *ci, Item *p_canvas_clip, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, const Transform2D &xform, const Rect2 &p_clip_rect, Rect2 global_rect, const Color &modulate, int p_z, RendererCanvasCull::Item *p_material_owner, bool p_use_canvas_group, RendererCanvasRender::Item *canvas_group_from, const Transform2D &p_xform);
private:
void _render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, 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);
void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, 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 allow_y_sort);
void _render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, 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 canvas_cull_mask);
void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, 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 allow_y_sort, uint32_t canvas_cull_mask);
RendererCanvasRender::Item **z_list;
RendererCanvasRender::Item **z_last_list;
public:
void render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, const Rect2 &p_clip_rect, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel);
void render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, const Rect2 &p_clip_rect, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel, uint32_t canvas_cull_mask);
bool was_sdf_used();
@ -206,6 +207,9 @@ public:
void canvas_item_set_visible(RID p_item, bool p_visible);
void canvas_item_set_light_mask(RID p_item, int p_mask);
void canvas_item_set_visibility_layer(RID p_item, uint32_t p_layer);
uint32_t canvas_item_get_visibility_layer(RID p_item);
void canvas_item_set_transform(RID p_item, const Transform2D &p_transform);
void canvas_item_set_clip(RID p_item, bool p_clip);
void canvas_item_set_distance_field_mode(RID p_item, bool p_enable);

View file

@ -530,7 +530,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
ptr = ptr->filter_next_ptr;
}
RSG::canvas->render_canvas(p_viewport->render_target, canvas, xform, canvas_lights, canvas_directional_lights, clip_rect, p_viewport->texture_filter, p_viewport->texture_repeat, p_viewport->snap_2d_transforms_to_pixel, p_viewport->snap_2d_vertices_to_pixel);
RSG::canvas->render_canvas(p_viewport->render_target, canvas, xform, canvas_lights, canvas_directional_lights, clip_rect, p_viewport->texture_filter, p_viewport->texture_repeat, p_viewport->snap_2d_transforms_to_pixel, p_viewport->snap_2d_vertices_to_pixel, p_viewport->canvas_cull_mask);
if (RSG::canvas->was_sdf_used()) {
p_viewport->sdf_active = true;
}
@ -1349,6 +1349,12 @@ void RendererViewport::set_default_clear_color(const Color &p_color) {
RSG::texture_storage->set_default_clear_color(p_color);
}
void RendererViewport::viewport_set_canvas_cull_mask(RID p_viewport, uint32_t p_canvas_cull_mask) {
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->canvas_cull_mask = p_canvas_cull_mask;
}
// Workaround for setting this on thread.
void RendererViewport::call_set_vsync_mode(DisplayServer::VSyncMode p_mode, DisplayServer::WindowID p_window) {
DisplayServer::get_singleton()->window_set_vsync_mode(p_mode, p_window);

View file

@ -117,6 +117,8 @@ public:
bool transparent_bg = false;
uint32_t canvas_cull_mask = 0xffffffff;
struct CanvasKey {
int64_t stacking;
RID canvas;
@ -249,6 +251,8 @@ public:
void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform);
void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer);
void viewport_set_canvas_cull_mask(RID p_viewport, uint32_t p_canvas_cull_mask);
void viewport_set_positional_shadow_atlas_size(RID p_viewport, int p_size, bool p_16_bits = true);
void viewport_set_positional_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv);

View file

@ -610,6 +610,8 @@ public:
FUNC2(viewport_set_disable_environment, RID, bool)
FUNC2(viewport_set_disable_3d, RID, bool)
FUNC2(viewport_set_canvas_cull_mask, RID, uint32_t)
FUNC2(viewport_attach_camera, RID, RID)
FUNC2(viewport_set_scenario, RID, RID)
FUNC2(viewport_attach_canvas, RID, RID)
@ -828,6 +830,8 @@ public:
FUNC2(canvas_item_set_visible, RID, bool)
FUNC2(canvas_item_set_light_mask, RID, int)
FUNC2(canvas_item_set_visibility_layer, RID, uint32_t)
FUNC2(canvas_item_set_update_when_visible, RID, bool)
FUNC2(canvas_item_set_transform, RID, const Transform2D &)

View file

@ -2182,6 +2182,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("viewport_set_parent_viewport", "viewport", "parent_viewport"), &RenderingServer::viewport_set_parent_viewport);
ClassDB::bind_method(D_METHOD("viewport_attach_to_screen", "viewport", "rect", "screen"), &RenderingServer::viewport_attach_to_screen, DEFVAL(Rect2()), DEFVAL(DisplayServer::MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("viewport_set_render_direct_to_screen", "viewport", "enabled"), &RenderingServer::viewport_set_render_direct_to_screen);
ClassDB::bind_method(D_METHOD("viewport_set_canvas_cull_mask", "viewport", "canvas_cull_mask"), &RenderingServer::viewport_set_canvas_cull_mask);
ClassDB::bind_method(D_METHOD("viewport_set_scaling_3d_mode", "viewport", "scaling_3d_mode"), &RenderingServer::viewport_set_scaling_3d_mode);
ClassDB::bind_method(D_METHOD("viewport_set_scaling_3d_scale", "viewport", "scale"), &RenderingServer::viewport_set_scaling_3d_scale);
@ -2575,6 +2576,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("canvas_item_set_default_texture_repeat", "item", "repeat"), &RenderingServer::canvas_item_set_default_texture_repeat);
ClassDB::bind_method(D_METHOD("canvas_item_set_visible", "item", "visible"), &RenderingServer::canvas_item_set_visible);
ClassDB::bind_method(D_METHOD("canvas_item_set_light_mask", "item", "mask"), &RenderingServer::canvas_item_set_light_mask);
ClassDB::bind_method(D_METHOD("canvas_item_set_visibility_layer", "item", "visibility_layer"), &RenderingServer::canvas_item_set_visibility_layer);
ClassDB::bind_method(D_METHOD("canvas_item_set_transform", "item", "transform"), &RenderingServer::canvas_item_set_transform);
ClassDB::bind_method(D_METHOD("canvas_item_set_clip", "item", "clip"), &RenderingServer::canvas_item_set_clip);
ClassDB::bind_method(D_METHOD("canvas_item_set_distance_field_mode", "item", "enabled"), &RenderingServer::canvas_item_set_distance_field_mode);

View file

@ -807,6 +807,7 @@ public:
virtual void viewport_set_size(RID p_viewport, int p_width, int p_height) = 0;
virtual void viewport_set_active(RID p_viewport, bool p_active) = 0;
virtual void viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) = 0;
virtual void viewport_set_canvas_cull_mask(RID p_viewport, uint32_t p_canvas_cull_mask) = 0;
virtual void viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect = Rect2(), DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) = 0;
virtual void viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable) = 0;
@ -1320,6 +1321,7 @@ public:
virtual void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect, const Rect2 &p_rect = Rect2()) = 0;
virtual void canvas_item_set_modulate(RID p_item, const Color &p_color) = 0;
virtual void canvas_item_set_self_modulate(RID p_item, const Color &p_color) = 0;
virtual void canvas_item_set_visibility_layer(RID p_item, uint32_t p_visibility_layer) = 0;
virtual void canvas_item_set_draw_behind_parent(RID p_item, bool p_enable) = 0;