summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/rendering/rasterizer_dummy.h15
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp137
-rw-r--r--servers/rendering/renderer_canvas_cull.h26
-rw-r--r--servers/rendering/renderer_canvas_render.h12
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp15
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp63
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h19
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl2
-rw-r--r--servers/rendering/renderer_scene.h1
-rw-r--r--servers/rendering/renderer_scene_cull.cpp47
-rw-r--r--servers/rendering/renderer_scene_cull.h19
-rw-r--r--servers/rendering/renderer_storage.h8
-rw-r--r--servers/rendering/rendering_server_default.cpp4
-rw-r--r--servers/rendering/rendering_server_default.h12
-rw-r--r--servers/rendering/rendering_server_globals.cpp2
-rw-r--r--servers/rendering/rendering_server_globals.h2
-rw-r--r--servers/rendering/shader_language.cpp2
-rw-r--r--servers/rendering_server.h20
18 files changed, 372 insertions, 34 deletions
diff --git a/servers/rendering/rasterizer_dummy.h b/servers/rendering/rasterizer_dummy.h
index b44088e822..d4c25b6253 100644
--- a/servers/rendering/rasterizer_dummy.h
+++ b/servers/rendering/rasterizer_dummy.h
@@ -621,9 +621,18 @@ public:
bool particles_collision_is_heightfield(RID p_particles_collision) const override { return false; }
RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override { return RID(); }
- RID particles_collision_instance_create(RID p_collision) override { return RID(); };
- void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override{};
- void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override{};
+ RID particles_collision_instance_create(RID p_collision) override { return RID(); }
+ void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override {}
+ void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override {}
+
+ /* VISIBILITY NOTIFIER */
+ virtual RID visibility_notifier_allocate() override { return RID(); }
+ virtual void visibility_notifier_initialize(RID p_notifier) override {}
+ virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) override {}
+ virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) override {}
+
+ virtual AABB visibility_notifier_get_aabb(RID p_notifier) const override { return AABB(); }
+ virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override {}
/* GLOBAL VARIABLES */
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index 6e126ea77e..016a172f25 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -104,7 +104,7 @@ void _mark_ysort_dirty(RendererCanvasCull::Item *ysort_owner, RID_PtrOwner<Rende
} while (ysort_owner && ysort_owner->sort_y);
}
-void _attach_canvas_item_for_draw(RendererCanvasCull::Item *ci, RendererCanvasCull::Item *p_canvas_clip, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **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 use_canvas_group, RendererCanvasRender::Item *canvas_group_from) {
+void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item *ci, RendererCanvasCull::Item *p_canvas_clip, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **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 use_canvas_group, RendererCanvasRender::Item *canvas_group_from, const Transform2D &p_xform) {
if (ci->copy_back_buffer) {
ci->copy_back_buffer->screen_rect = xform.xform(ci->copy_back_buffer->rect).intersection(p_clip_rect);
}
@@ -173,32 +173,44 @@ void _attach_canvas_item_for_draw(RendererCanvasCull::Item *ci, RendererCanvasCu
}
}
- if (ci->update_when_visible) {
- RenderingServerDefault::redraw_request();
- }
-
- if ((ci->commands != nullptr && p_clip_rect.intersects(global_rect, true)) || ci->vp_render || ci->copy_back_buffer) {
+ if (((ci->commands != nullptr || ci->visibility_notifier) && p_clip_rect.intersects(global_rect, true)) || ci->vp_render || ci->copy_back_buffer) {
//something to draw?
- ci->final_transform = xform;
- ci->final_modulate = Color(modulate.r * ci->self_modulate.r, modulate.g * ci->self_modulate.g, modulate.b * ci->self_modulate.b, modulate.a * ci->self_modulate.a);
- ci->global_rect_cache = global_rect;
- ci->global_rect_cache.position -= p_clip_rect.position;
- ci->light_masked = false;
- int zidx = p_z - RS::CANVAS_ITEM_Z_MIN;
+ if (ci->update_when_visible) {
+ RenderingServerDefault::redraw_request();
+ }
- if (z_last_list[zidx]) {
- z_last_list[zidx]->next = ci;
- z_last_list[zidx] = ci;
+ if (ci->commands != nullptr) {
+ ci->final_transform = xform;
+ ci->final_modulate = Color(modulate.r * ci->self_modulate.r, modulate.g * ci->self_modulate.g, modulate.b * ci->self_modulate.b, modulate.a * ci->self_modulate.a);
+ ci->global_rect_cache = global_rect;
+ ci->global_rect_cache.position -= p_clip_rect.position;
+ ci->light_masked = false;
- } else {
- z_list[zidx] = ci;
- z_last_list[zidx] = ci;
+ int zidx = p_z - RS::CANVAS_ITEM_Z_MIN;
+
+ if (z_last_list[zidx]) {
+ z_last_list[zidx]->next = ci;
+ z_last_list[zidx] = ci;
+
+ } else {
+ z_list[zidx] = ci;
+ z_last_list[zidx] = ci;
+ }
+
+ ci->z_final = p_z;
+
+ ci->next = nullptr;
}
- ci->z_final = p_z;
+ if (ci->visibility_notifier) {
+ if (!ci->visibility_notifier->visible_element.in_list()) {
+ visibility_notifier_list.add(&ci->visibility_notifier->visible_element);
+ ci->visibility_notifier->just_visible = true;
+ }
- ci->next = nullptr;
+ ci->visibility_notifier->visible_in_frame = RSG::rasterizer->get_frame_number();
+ }
}
}
@@ -215,6 +227,13 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
}
Rect2 rect = ci->get_rect();
+
+ if (ci->visibility_notifier) {
+ if (ci->visibility_notifier->area.size != Vector2()) {
+ rect = rect.merge(ci->visibility_notifier->area);
+ }
+ }
+
Transform2D xform = ci->xform;
if (snapping_2d_transforms_to_pixel) {
xform.elements[2] = xform.elements[2].floor();
@@ -289,7 +308,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
canvas_group_from = z_last_list[zidx];
}
- _attach_canvas_item_for_draw(ci, p_canvas_clip, z_list, z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from);
+ _attach_canvas_item_for_draw(ci, p_canvas_clip, z_list, z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from, xform);
}
} else {
RendererCanvasRender::Item *canvas_group_from = nullptr;
@@ -305,7 +324,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
}
_cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true);
}
- _attach_canvas_item_for_draw(ci, p_canvas_clip, z_list, z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from);
+ _attach_canvas_item_for_draw(ci, p_canvas_clip, z_list, 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;
@@ -984,6 +1003,18 @@ void RendererCanvasCull::canvas_item_add_clip_ignore(RID p_item, bool p_ignore)
ci->ignore = p_ignore;
}
+void RendererCanvasCull::canvas_item_add_animation_slice(RID p_item, double p_animation_length, double p_slice_begin, double p_slice_end, double p_offset) {
+ Item *canvas_item = canvas_item_owner.getornull(p_item);
+ ERR_FAIL_COND(!canvas_item);
+
+ Item::CommandAnimationSlice *as = canvas_item->alloc_command<Item::CommandAnimationSlice>();
+ ERR_FAIL_COND(!as);
+ as->animation_length = p_animation_length;
+ as->slice_begin = p_slice_begin;
+ as->slice_end = p_slice_end;
+ as->offset = p_offset;
+}
+
void RendererCanvasCull::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -1095,6 +1126,26 @@ void RendererCanvasCull::canvas_item_set_use_parent_material(RID p_item, bool p_
canvas_item->use_parent_material = p_enable;
}
+void RendererCanvasCull::canvas_item_set_visibility_notifier(RID p_item, bool p_enable, const Rect2 &p_area, const Callable &p_enter_callable, const Callable &p_exit_callable) {
+ Item *canvas_item = canvas_item_owner.getornull(p_item);
+ ERR_FAIL_COND(!canvas_item);
+
+ if (p_enable) {
+ if (!canvas_item->visibility_notifier) {
+ canvas_item->visibility_notifier = visibility_notifier_allocator.alloc();
+ }
+ canvas_item->visibility_notifier->area = p_area;
+ canvas_item->visibility_notifier->enter_callable = p_enter_callable;
+ canvas_item->visibility_notifier->exit_callable = p_exit_callable;
+
+ } else {
+ if (canvas_item->visibility_notifier) {
+ visibility_notifier_allocator.free(canvas_item->visibility_notifier);
+ canvas_item->visibility_notifier = nullptr;
+ }
+ }
+}
+
void RendererCanvasCull::canvas_item_set_canvas_group_mode(RID p_item, RS::CanvasGroupMode p_mode, float p_clear_margin, bool p_fit_empty, float p_fit_margin, bool p_blur_mipmaps) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -1477,6 +1528,44 @@ void RendererCanvasCull::canvas_item_set_default_texture_repeat(RID p_item, RS::
ci->texture_repeat = p_repeat;
}
+void RendererCanvasCull::update_visibility_notifiers() {
+ SelfList<Item::VisibilityNotifierData> *E = visibility_notifier_list.first();
+ while (E) {
+ SelfList<Item::VisibilityNotifierData> *N = E->next();
+
+ Item::VisibilityNotifierData *visibility_notifier = E->self();
+ if (visibility_notifier->just_visible) {
+ visibility_notifier->just_visible = false;
+
+ if (!visibility_notifier->enter_callable.is_null()) {
+ if (RSG::threaded) {
+ visibility_notifier->enter_callable.call_deferred(nullptr, 0);
+ } else {
+ Callable::CallError ce;
+ Variant ret;
+ visibility_notifier->enter_callable.call(nullptr, 0, ret, ce);
+ }
+ }
+ } else {
+ if (visibility_notifier->visible_in_frame != RSG::rasterizer->get_frame_number()) {
+ visibility_notifier_list.remove(E);
+
+ if (!visibility_notifier->exit_callable.is_null()) {
+ if (RSG::threaded) {
+ visibility_notifier->exit_callable.call_deferred(nullptr, 0);
+ } else {
+ Callable::CallError ce;
+ Variant ret;
+ visibility_notifier->exit_callable.call(nullptr, 0, ret, ce);
+ }
+ }
+ }
+ }
+
+ E = N;
+ }
+}
+
bool RendererCanvasCull::free(RID p_rid) {
if (canvas_owner.owns(p_rid)) {
Canvas *canvas = canvas_owner.getornull(p_rid);
@@ -1531,6 +1620,10 @@ bool RendererCanvasCull::free(RID p_rid) {
canvas_item->child_items[i]->parent = RID();
}
+ if (canvas_item->visibility_notifier != nullptr) {
+ visibility_notifier_allocator.free(canvas_item->visibility_notifier);
+ }
+
/*
if (canvas_item->material) {
canvas_item->material->owners.erase(canvas_item);
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index 37391d7c0e..a51b419613 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -31,6 +31,7 @@
#ifndef RENDERING_SERVER_CANVAS_CULL_H
#define RENDERING_SERVER_CANVAS_CULL_H
+#include "core/templates/paged_allocator.h"
#include "renderer_compositor.h"
#include "renderer_viewport.h"
@@ -55,6 +56,20 @@ public:
Vector<Item *> child_items;
+ struct VisibilityNotifierData {
+ Rect2 area;
+ Callable enter_callable;
+ Callable exit_callable;
+ bool just_visible = false;
+ uint64_t visible_in_frame = 0;
+ SelfList<VisibilityNotifierData> visible_element;
+ VisibilityNotifierData() :
+ visible_element(this) {
+ }
+ };
+
+ VisibilityNotifierData *visibility_notifier = nullptr;
+
Item() {
children_order_dirty = true;
E = nullptr;
@@ -156,6 +171,11 @@ public:
bool sdf_used = false;
bool snapping_2d_transforms_to_pixel = false;
+ PagedAllocator<Item::VisibilityNotifierData> visibility_notifier_allocator;
+ SelfList<Item::VisibilityNotifierData>::List visibility_notifier_list;
+
+ _FORCE_INLINE_ void _attach_canvas_item_for_draw(Item *ci, Item *p_canvas_clip, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **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 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 **z_list, RendererCanvasRender::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool allow_y_sort);
@@ -211,6 +231,8 @@ public:
void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture);
void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform);
void canvas_item_add_clip_ignore(RID p_item, bool p_ignore);
+ void canvas_item_add_animation_slice(RID p_item, double p_animation_length, double p_slice_begin, double p_slice_end, double p_offset);
+
void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable);
void canvas_item_set_z_index(RID p_item, int p_z);
void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable);
@@ -224,6 +246,8 @@ public:
void canvas_item_set_use_parent_material(RID p_item, bool p_enable);
+ void canvas_item_set_visibility_notifier(RID p_item, bool p_enable, const Rect2 &p_area, const Callable &p_enter_callable, const Callable &p_exit_callable);
+
void canvas_item_set_canvas_group_mode(RID p_item, RS::CanvasGroupMode p_mode, float p_clear_margin = 5.0, bool p_fit_empty = false, float p_fit_margin = 0.0, bool p_blur_mipmaps = false);
RID canvas_light_allocate();
@@ -283,6 +307,8 @@ public:
void canvas_item_set_default_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter);
void canvas_item_set_default_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat);
+ void update_visibility_notifiers();
+
bool free(RID p_rid);
RendererCanvasCull();
~RendererCanvasCull();
diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h
index 0266e137c0..c10b9db035 100644
--- a/servers/rendering/renderer_canvas_render.h
+++ b/servers/rendering/renderer_canvas_render.h
@@ -180,6 +180,7 @@ public:
TYPE_PARTICLES,
TYPE_TRANSFORM,
TYPE_CLIP_IGNORE,
+ TYPE_ANIMATION_SLICE,
};
Command *next;
@@ -286,6 +287,17 @@ public:
}
};
+ struct CommandAnimationSlice : public Command {
+ double animation_length = 0;
+ double slice_begin = 0;
+ double slice_end = 0;
+ double offset = 0;
+
+ CommandAnimationSlice() {
+ type = TYPE_ANIMATION_SLICE;
+ }
+ };
+
struct ViewportRender {
RenderingServer *owner;
void *udata;
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 9d325fe69b..fe6d3be82e 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -464,8 +464,15 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
RID last_texture;
Size2 texpixel_size;
+ bool skipping = false;
+
const Item::Command *c = p_item->commands;
while (c) {
+ if (skipping && c->type != Item::Command::TYPE_ANIMATION_SLICE) {
+ c = c->next;
+ continue;
+ }
+
push_constant.flags = base_flags | (push_constant.flags & (FLAGS_DEFAULT_NORMAL_MAP_USED | FLAGS_DEFAULT_SPECULAR_MAP_USED)); //reset on each command for sanity, keep canvastexture binding config
switch (c->type) {
@@ -879,6 +886,14 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
}
} break;
+ case Item::Command::TYPE_ANIMATION_SLICE: {
+ const Item::CommandAnimationSlice *as = static_cast<const Item::CommandAnimationSlice *>(c);
+ double current_time = RendererCompositorRD::singleton->get_total_time();
+ double local_time = Math::fposmod(current_time - as->offset, as->animation_length);
+ skipping = !(local_time >= as->slice_begin && local_time < as->slice_end);
+
+ RenderingServerDefault::redraw_request(); // animation visible means redraw request
+ } break;
}
c = c->next;
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
index 64be54115f..246b5f0e4c 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
@@ -5535,6 +5535,59 @@ void RendererStorageRD::particles_collision_instance_set_active(RID p_collision_
pci->active = p_active;
}
+/* VISIBILITY NOTIFIER */
+
+RID RendererStorageRD::visibility_notifier_allocate() {
+ return visibility_notifier_owner.allocate_rid();
+}
+void RendererStorageRD::visibility_notifier_initialize(RID p_notifier) {
+ visibility_notifier_owner.initialize_rid(p_notifier, VisibilityNotifier());
+}
+void RendererStorageRD::visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) {
+ VisibilityNotifier *vn = visibility_notifier_owner.getornull(p_notifier);
+ ERR_FAIL_COND(!vn);
+ vn->aabb = p_aabb;
+ vn->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
+}
+void RendererStorageRD::visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) {
+ VisibilityNotifier *vn = visibility_notifier_owner.getornull(p_notifier);
+ ERR_FAIL_COND(!vn);
+ vn->enter_callback = p_enter_callbable;
+ vn->exit_callback = p_exit_callable;
+}
+
+AABB RendererStorageRD::visibility_notifier_get_aabb(RID p_notifier) const {
+ const VisibilityNotifier *vn = visibility_notifier_owner.getornull(p_notifier);
+ ERR_FAIL_COND_V(!vn, AABB());
+ return vn->aabb;
+}
+void RendererStorageRD::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) {
+ VisibilityNotifier *vn = visibility_notifier_owner.getornull(p_notifier);
+ ERR_FAIL_COND(!vn);
+
+ if (p_enter) {
+ if (!vn->enter_callback.is_null()) {
+ if (p_deferred) {
+ vn->enter_callback.call_deferred(nullptr, 0);
+ } else {
+ Variant r;
+ Callable::CallError ce;
+ vn->enter_callback.call(nullptr, 0, r, ce);
+ }
+ }
+ } else {
+ if (!vn->exit_callback.is_null()) {
+ if (p_deferred) {
+ vn->exit_callback.call_deferred(nullptr, 0);
+ } else {
+ Variant r;
+ Callable::CallError ce;
+ vn->exit_callback.call(nullptr, 0, r, ce);
+ }
+ }
+ }
+}
+
/* SKELETON API */
RID RendererStorageRD::skeleton_allocate() {
@@ -7590,6 +7643,9 @@ void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_
} else if (particles_collision_owner.owns(p_base)) {
ParticlesCollision *pc = particles_collision_owner.getornull(p_base);
p_instance->update_dependency(&pc->dependency);
+ } else if (visibility_notifier_owner.owns(p_base)) {
+ VisibilityNotifier *vn = visibility_notifier_owner.getornull(p_base);
+ p_instance->update_dependency(&vn->dependency);
}
}
@@ -7628,6 +7684,9 @@ RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const {
if (particles_collision_owner.owns(p_rid)) {
return RS::INSTANCE_PARTICLES_COLLISION;
}
+ if (visibility_notifier_owner.owns(p_rid)) {
+ return RS::INSTANCE_VISIBLITY_NOTIFIER;
+ }
return RS::INSTANCE_NONE;
}
@@ -8704,6 +8763,10 @@ bool RendererStorageRD::free(RID p_rid) {
}
particles_collision->dependency.deleted_notify(p_rid);
particles_collision_owner.free(p_rid);
+ } else if (visibility_notifier_owner.owns(p_rid)) {
+ VisibilityNotifier *vn = visibility_notifier_owner.getornull(p_rid);
+ vn->dependency.deleted_notify(p_rid);
+ visibility_notifier_owner.free(p_rid);
} else if (particles_collision_instance_owner.owns(p_rid)) {
particles_collision_instance_owner.free(p_rid);
} else if (render_target_owner.owns(p_rid)) {
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h
index 28a1044705..ab470cb3a6 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.h
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.h
@@ -947,6 +947,17 @@ private:
mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner;
+ /* visibility_notifier */
+
+ struct VisibilityNotifier {
+ AABB aabb;
+ Callable enter_callback;
+ Callable exit_callback;
+ Dependency dependency;
+ };
+
+ mutable RID_Owner<VisibilityNotifier> visibility_notifier_owner;
+
/* Skeleton */
struct Skeleton {
@@ -2253,6 +2264,14 @@ public:
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const;
RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const;
+ virtual RID visibility_notifier_allocate();
+ virtual void visibility_notifier_initialize(RID p_notifier);
+ virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb);
+ virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable);
+
+ virtual AABB visibility_notifier_get_aabb(RID p_notifier) const;
+ virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred);
+
//used from 2D and 3D
virtual RID particles_collision_instance_create(RID p_collision);
virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform);
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index ce02d5c4d0..8538030263 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -904,7 +904,7 @@ void main() {
}
#endif // USE_LIGHTMAP
#if defined(CUSTOM_IRRADIANCE_USED)
- ambient_light = mix(specular_light, custom_irradiance.rgb, custom_irradiance.a);
+ ambient_light = mix(ambient_light, custom_irradiance.rgb, custom_irradiance.a);
#endif
#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h
index 3b25498ed8..d71425f465 100644
--- a/servers/rendering/renderer_scene.h
+++ b/servers/rendering/renderer_scene.h
@@ -207,6 +207,7 @@ public:
virtual void update() = 0;
virtual void render_probes() = 0;
+ virtual void update_visibility_notifiers() = 0;
virtual bool free(RID p_rid) = 0;
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 2c66b22089..efaf77f30b 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -506,6 +506,9 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(instance->base_data);
RSG::storage->free(collision->instance);
} break;
+ case RS::INSTANCE_VISIBLITY_NOTIFIER: {
+ //none
+ } break;
case RS::INSTANCE_REFLECTION_PROBE: {
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data);
scene_render->free(reflection_probe->instance);
@@ -615,6 +618,11 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
RSG::storage->particles_collision_instance_set_active(collision->instance, instance->visible);
instance->base_data = collision;
} break;
+ case RS::INSTANCE_VISIBLITY_NOTIFIER: {
+ InstanceVisibilityNotifierData *vnd = memnew(InstanceVisibilityNotifierData);
+ vnd->base = p_base;
+ instance->base_data = vnd;
+ } break;
case RS::INSTANCE_REFLECTION_PROBE: {
InstanceReflectionProbeData *reflection_probe = memnew(InstanceReflectionProbeData);
reflection_probe->owner = instance;
@@ -1549,6 +1557,9 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
case RS::INSTANCE_VOXEL_GI: {
idata.instance_data_rid = static_cast<InstanceVoxelGIData *>(p_instance->base_data)->probe_instance.get_id();
} break;
+ case RS::INSTANCE_VISIBLITY_NOTIFIER: {
+ idata.visibility_notifier = static_cast<InstanceVisibilityNotifierData *>(p_instance->base_data);
+ } break;
default: {
}
}
@@ -1758,6 +1769,9 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
new_aabb = RSG::storage->particles_collision_get_aabb(p_instance->base);
} break;
+ case RenderingServer::INSTANCE_VISIBLITY_NOTIFIER: {
+ new_aabb = RSG::storage->visibility_notifier_get_aabb(p_instance->base);
+ } break;
case RenderingServer::INSTANCE_LIGHT: {
new_aabb = RSG::storage->light_get_aabb(p_instance->base);
@@ -2567,7 +2581,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
#define VIS_RANGE_CHECK ((idata.visibility_index == -1) || _visibility_range_check(cull_data.scenario->instance_visibility[idata.visibility_index], cull_data.cam_transform.origin, cull_data.visibility_cull_data->viewport_mask) == 0)
#define VIS_PARENT_CHECK ((idata.parent_array_index == -1) || ((cull_data.scenario->instance_data[idata.parent_array_index].flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK) == InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE))
#define VIS_CHECK (visibility_check < 0 ? (visibility_check = (visibility_flags != InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK || (VIS_RANGE_CHECK && VIS_PARENT_CHECK))) : visibility_check)
-#define OCCLUSION_CULLED (cull_data.occlusion_buffer != nullptr && cull_data.scenario->instance_data[i].flags & InstanceData::FLAG_IGNORE_OCCLUSION_CULLING && cull_data.occlusion_buffer->is_occluded(cull_data.scenario->instance_aabbs[i].bounds, cull_data.cam_transform.origin, inv_cam_transform, *cull_data.camera_matrix, z_near))
+#define OCCLUSION_CULLED (cull_data.occlusion_buffer != nullptr && (cull_data.scenario->instance_data[i].flags & InstanceData::FLAG_IGNORE_OCCLUSION_CULLING) == 0 && cull_data.occlusion_buffer->is_occluded(cull_data.scenario->instance_aabbs[i].bounds, cull_data.cam_transform.origin, inv_cam_transform, *cull_data.camera_matrix, z_near))
if (!HIDDEN_BY_VISIBILITY_CHECKS) {
if (LAYER_CHECK && IN_FRUSTUM(cull_data.cull->frustum) && VIS_CHECK && !OCCLUSION_CULLED) {
@@ -2613,6 +2627,15 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
} else if (base_type == RS::INSTANCE_LIGHTMAP) {
cull_result.lightmaps.push_back(RID::from_uint64(idata.instance_data_rid));
+ } else if (base_type == RS::INSTANCE_VISIBLITY_NOTIFIER) {
+ InstanceVisibilityNotifierData *vnd = idata.visibility_notifier;
+ if (!vnd->list_element.in_list()) {
+ visible_notifier_list_lock.lock();
+ visible_notifier_list.add(&vnd->list_element);
+ visible_notifier_list_lock.unlock();
+ vnd->just_visible = true;
+ }
+ vnd->visible_in_frame = RSG::rasterizer->get_frame_number();
} else if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && !(idata.flags & InstanceData::FLAG_CAST_SHADOWS_ONLY)) {
bool keep = true;
@@ -3849,6 +3872,28 @@ TypedArray<Image> RendererSceneCull::bake_render_uv2(RID p_base, const Vector<RI
return scene_render->bake_render_uv2(p_base, p_material_overrides, p_image_size);
}
+void RendererSceneCull::update_visibility_notifiers() {
+ SelfList<InstanceVisibilityNotifierData> *E = visible_notifier_list.first();
+ while (E) {
+ SelfList<InstanceVisibilityNotifierData> *N = E->next();
+
+ InstanceVisibilityNotifierData *visibility_notifier = E->self();
+ if (visibility_notifier->just_visible) {
+ visibility_notifier->just_visible = false;
+
+ RSG::storage->visibility_notifier_call(visibility_notifier->base, true, RSG::threaded);
+ } else {
+ if (visibility_notifier->visible_in_frame != RSG::rasterizer->get_frame_number()) {
+ visible_notifier_list.remove(E);
+
+ RSG::storage->visibility_notifier_call(visibility_notifier->base, false, RSG::threaded);
+ }
+ }
+
+ E = N;
+ }
+}
+
/*******************************/
/* Passthrough to Scene Render */
/*******************************/
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index bdfbea95a2..d9466d8b04 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -118,6 +118,8 @@ public:
virtual void occluder_initialize(RID p_occluder);
virtual void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices);
+ /* VISIBILITY NOTIFIER API */
+
RendererSceneOcclusionCull *dummy_occlusion_culling;
/* SCENARIO API */
@@ -243,6 +245,8 @@ public:
}
};
+ struct InstanceVisibilityNotifierData;
+
struct InstanceData {
// Store instance pointer as well as common instance processing information,
// to make processing more cache friendly.
@@ -271,6 +275,7 @@ public:
union {
uint64_t instance_data_rid;
RendererSceneRender::GeometryInstance *instance_geometry;
+ InstanceVisibilityNotifierData *visibility_notifier;
};
Instance *instance = nullptr;
int32_t parent_array_index = -1;
@@ -611,6 +616,18 @@ public:
RID instance;
};
+ struct InstanceVisibilityNotifierData : public InstanceBaseData {
+ bool just_visible = false;
+ uint64_t visible_in_frame = 0;
+ RID base;
+ SelfList<InstanceVisibilityNotifierData> list_element;
+ InstanceVisibilityNotifierData() :
+ list_element(this) {}
+ };
+
+ SpinLock visible_notifier_list_lock;
+ SelfList<InstanceVisibilityNotifierData>::List visible_notifier_list;
+
struct InstanceLightData : public InstanceBaseData {
RID instance;
uint64_t last_version;
@@ -1123,6 +1140,8 @@ public:
void set_scene_render(RendererSceneRender *p_scene_render);
+ virtual void update_visibility_notifiers();
+
RendererSceneCull();
virtual ~RendererSceneCull();
};
diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h
index e6b9ac15ff..f22c582f48 100644
--- a/servers/rendering/renderer_storage.h
+++ b/servers/rendering/renderer_storage.h
@@ -557,6 +557,14 @@ public:
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const = 0;
virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const = 0;
+ virtual RID visibility_notifier_allocate() = 0;
+ virtual void visibility_notifier_initialize(RID p_notifier) = 0;
+ virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) = 0;
+ virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) = 0;
+
+ virtual AABB visibility_notifier_get_aabb(RID p_notifier) const = 0;
+ virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) = 0;
+
//used from 2D and 3D
virtual RID particles_collision_instance_create(RID p_collision) = 0;
virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) = 0;
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index cd66cd0716..629d212b69 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -117,6 +117,9 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
_draw_margins();
RSG::rasterizer->end_frame(p_swap_buffers);
+ RSG::canvas->update_visibility_notifiers();
+ RSG::scene->update_visibility_notifiers();
+
while (frame_drawn_callbacks.front()) {
Object *obj = ObjectDB::get_instance(frame_drawn_callbacks.front()->get().object);
if (obj) {
@@ -396,6 +399,7 @@ RenderingServerDefault::RenderingServerDefault(bool p_create_thread) :
server_thread = 0;
}
+ RSG::threaded = p_create_thread;
RSG::canvas = memnew(RendererCanvasCull);
RSG::viewport = memnew(RendererViewport);
RendererSceneCull *sr = memnew(RendererSceneCull);
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index e4d319ed6c..16e9f1fc77 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -529,6 +529,12 @@ public:
FUNC1(particles_collision_height_field_update, RID)
FUNC2(particles_collision_set_height_field_resolution, RID, ParticlesCollisionHeightfieldResolution)
+ /* VISIBILITY_NOTIFIER */
+
+ FUNCRIDSPLIT(visibility_notifier)
+ FUNC2(visibility_notifier_set_aabb, RID, const AABB &)
+ FUNC3(visibility_notifier_set_callbacks, RID, const Callable &, const Callable &)
+
#undef server_name
#undef ServerName
//from now on, calls forwarded to this singleton
@@ -549,7 +555,7 @@ public:
/* OCCLUDER */
FUNCRIDSPLIT(occluder)
- FUNC3(occluder_set_mesh, RID, const PackedVector3Array &, const PackedInt32Array &);
+ FUNC3(occluder_set_mesh, RID, const PackedVector3Array &, const PackedInt32Array &)
#undef server_name
#undef ServerName
@@ -807,6 +813,8 @@ public:
FUNC3(canvas_item_add_particles, RID, RID, RID)
FUNC2(canvas_item_add_set_transform, RID, const Transform2D &)
FUNC2(canvas_item_add_clip_ignore, RID, bool)
+ FUNC5(canvas_item_add_animation_slice, RID, double, double, double, double)
+
FUNC2(canvas_item_set_sort_children_by_y, RID, bool)
FUNC2(canvas_item_set_z_index, RID, int)
FUNC2(canvas_item_set_z_as_relative_to_parent, RID, bool)
@@ -820,6 +828,8 @@ public:
FUNC2(canvas_item_set_use_parent_material, RID, bool)
+ FUNC5(canvas_item_set_visibility_notifier, RID, bool, const Rect2 &, const Callable &, const Callable &)
+
FUNC6(canvas_item_set_canvas_group_mode, RID, CanvasGroupMode, float, bool, float, bool)
FUNCRIDSPLIT(canvas_light)
diff --git a/servers/rendering/rendering_server_globals.cpp b/servers/rendering/rendering_server_globals.cpp
index c0d9988e85..2dda506bac 100644
--- a/servers/rendering/rendering_server_globals.cpp
+++ b/servers/rendering/rendering_server_globals.cpp
@@ -30,6 +30,8 @@
#include "rendering_server_globals.h"
+bool RenderingServerGlobals::threaded = false;
+
RendererStorage *RenderingServerGlobals::storage = nullptr;
RendererCanvasRender *RenderingServerGlobals::canvas_render = nullptr;
RendererCompositor *RenderingServerGlobals::rasterizer = nullptr;
diff --git a/servers/rendering/rendering_server_globals.h b/servers/rendering/rendering_server_globals.h
index a28a0f5180..63755e6125 100644
--- a/servers/rendering/rendering_server_globals.h
+++ b/servers/rendering/rendering_server_globals.h
@@ -41,6 +41,8 @@ class RendererScene;
class RenderingServerGlobals {
public:
+ static bool threaded;
+
static RendererStorage *storage;
static RendererCanvasRender *canvas_render;
static RendererCompositor *rasterizer;
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 8ed774f8e7..9b2ba36358 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -631,7 +631,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
if (!_is_number(last_char)) {
return _make_token(TK_ERROR, "Invalid (integer) numeric constant");
}
- if (!str.is_valid_integer()) {
+ if (!str.is_valid_int()) {
return _make_token(TK_ERROR, "Invalid numeric constant");
}
}
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 1806f1da18..594e2d885c 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -722,6 +722,17 @@ public:
virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, ParticlesCollisionHeightfieldResolution p_resolution) = 0; //for SDF and vector field
+ /* VISIBILITY NOTIFIER API */
+
+ virtual RID visibility_notifier_create() = 0;
+ virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) = 0;
+ virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) = 0;
+
+ /* OCCLUDER API */
+
+ virtual RID occluder_create() = 0;
+ virtual void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) = 0;
+
/* CAMERA API */
virtual RID camera_create() = 0;
@@ -734,11 +745,6 @@ public:
virtual void camera_set_camera_effects(RID p_camera, RID p_camera_effects) = 0;
virtual void camera_set_use_vertical_aspect(RID p_camera, bool p_enable) = 0;
- /* OCCLUDER API */
-
- virtual RID occluder_create() = 0;
- virtual void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) = 0;
-
/* VIEWPORT TARGET API */
enum CanvasItemTextureFilter {
@@ -1148,6 +1154,7 @@ public:
INSTANCE_VOXEL_GI,
INSTANCE_LIGHTMAP,
INSTANCE_OCCLUDER,
+ INSTANCE_VISIBLITY_NOTIFIER,
INSTANCE_MAX,
INSTANCE_GEOMETRY_MASK = (1 << INSTANCE_MESH) | (1 << INSTANCE_MULTIMESH) | (1 << INSTANCE_IMMEDIATE) | (1 << INSTANCE_PARTICLES)
@@ -1287,6 +1294,7 @@ public:
virtual void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture) = 0;
virtual void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform) = 0;
virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore) = 0;
+ virtual void canvas_item_add_animation_slice(RID p_item, double p_animation_length, double p_slice_begin, double p_slice_end, double p_offset) = 0;
virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) = 0;
virtual void canvas_item_set_z_index(RID p_item, int p_z) = 0;
virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable) = 0;
@@ -1301,6 +1309,8 @@ public:
virtual void canvas_item_set_use_parent_material(RID p_item, bool p_enable) = 0;
+ virtual void canvas_item_set_visibility_notifier(RID p_item, bool p_enable, const Rect2 &p_area, const Callable &p_enter_callbable, const Callable &p_exit_callable) = 0;
+
enum CanvasGroupMode {
CANVAS_GROUP_MODE_DISABLED,
CANVAS_GROUP_MODE_OPAQUE,