diff options
Diffstat (limited to 'servers')
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, |