diff options
Diffstat (limited to 'servers')
97 files changed, 1916 insertions, 787 deletions
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 774a5b1da0..f7c8f0921c 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -762,7 +762,7 @@ void AudioServer::remove_bus(int p_index) { lock(); bus_map.erase(buses[p_index]->name); memdelete(buses[p_index]); - buses.remove(p_index); + buses.remove_at(p_index); unlock(); emit_signal(SNAME("bus_layout_changed")); @@ -833,7 +833,7 @@ void AudioServer::move_bus(int p_bus, int p_to_pos) { } Bus *bus = buses[p_bus]; - buses.remove(p_bus); + buses.remove_at(p_bus); if (p_to_pos == -1) { buses.push_back(bus); @@ -1026,7 +1026,7 @@ void AudioServer::remove_bus_effect(int p_bus, int p_effect) { lock(); - buses[p_bus]->effects.remove(p_effect); + buses[p_bus]->effects.remove_at(p_effect); _update_bus_effects(p_bus); unlock(); diff --git a/servers/camera_server.cpp b/servers/camera_server.cpp index 6f506d0f7a..8391a2ee2e 100644 --- a/servers/camera_server.cpp +++ b/servers/camera_server.cpp @@ -124,7 +124,7 @@ void CameraServer::remove_feed(const Ref<CameraFeed> &p_feed) { #endif // remove it from our array, if this results in our feed being unreferenced it will be destroyed - feeds.remove(i); + feeds.remove_at(i); // let whomever is interested know emit_signal(SNAME("camera_feed_removed"), feed_id); diff --git a/servers/display_server.cpp b/servers/display_server.cpp index 7bf5673663..8b5a965738 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -148,7 +148,7 @@ Point2i DisplayServer::mouse_get_position() const { } MouseButton DisplayServer::mouse_get_button_state() const { - ERR_FAIL_V_MSG(MOUSE_BUTTON_NONE, "Mouse is not supported by this display server."); + ERR_FAIL_V_MSG(MouseButton::NONE, "Mouse is not supported by this display server."); } void DisplayServer::clipboard_set(const String &p_text) { diff --git a/servers/display_server_headless.h b/servers/display_server_headless.h index d9ee91084f..0837e41db8 100644 --- a/servers/display_server_headless.h +++ b/servers/display_server_headless.h @@ -65,7 +65,11 @@ public: Vector<DisplayServer::WindowID> get_window_list() const override { return Vector<DisplayServer::WindowID>(); } - WindowID get_window_at_screen_position(const Point2i &p_position) const override { return -1; } + WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override { return 0; } + void show_window(WindowID p_id) override {} + void delete_sub_window(WindowID p_id) override {} + + WindowID get_window_at_screen_position(const Point2i &p_position) const override { return 0; } void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override {} ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override { return ObjectID(); } @@ -93,7 +97,7 @@ public: Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const override { return Size2i(); } void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override {} - Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const override { return Size2i(); }; + Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const override { return Size2i(); } void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override {} Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const override { return Size2i(); } @@ -102,10 +106,13 @@ public: void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) override {} WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const override { return WINDOW_MODE_MINIMIZED; } + void window_set_vsync_mode(VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override {} + VSyncMode window_get_vsync_mode(WindowID p_window) const override { return VSyncMode::VSYNC_ENABLED; } + bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const override { return false; } void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID) override {} - virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const override { return false; } + bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const override { return false; } void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) override {} void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override {} @@ -114,6 +121,9 @@ public: bool can_any_window_draw() const override { return false; } + void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID) override {} + void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID) override {} + void process_events() override {} void set_icon(const Ref<Image> &p_icon) override {} diff --git a/servers/physics_2d/godot_area_2d.cpp b/servers/physics_2d/godot_area_2d.cpp index 6983e28841..c4060615c9 100644 --- a/servers/physics_2d/godot_area_2d.cpp +++ b/servers/physics_2d/godot_area_2d.cpp @@ -121,18 +121,21 @@ void GodotArea2D::set_area_monitor_callback(const Callable &p_callback) { } } -void GodotArea2D::set_space_override_mode(PhysicsServer2D::AreaSpaceOverrideMode p_mode) { - bool do_override = p_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED; - if (do_override == (space_override_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED)) { +void GodotArea2D::_set_space_override_mode(PhysicsServer2D::AreaSpaceOverrideMode &r_mode, PhysicsServer2D::AreaSpaceOverrideMode p_new_mode) { + bool do_override = p_new_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED; + if (do_override == (r_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED)) { return; } _unregister_shapes(); - space_override_mode = p_mode; + r_mode = p_new_mode; _shape_changed(); } void GodotArea2D::set_param(PhysicsServer2D::AreaParameter p_param, const Variant &p_value) { switch (p_param) { + case PhysicsServer2D::AREA_PARAM_GRAVITY_OVERRIDE_MODE: + _set_space_override_mode(gravity_override_mode, (PhysicsServer2D::AreaSpaceOverrideMode)(int)p_value); + break; case PhysicsServer2D::AREA_PARAM_GRAVITY: gravity = p_value; break; @@ -148,9 +151,15 @@ void GodotArea2D::set_param(PhysicsServer2D::AreaParameter p_param, const Varian case PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_ATTENUATION: point_attenuation = p_value; break; + case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE: + _set_space_override_mode(linear_damping_override_mode, (PhysicsServer2D::AreaSpaceOverrideMode)(int)p_value); + break; case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP: linear_damp = p_value; break; + case PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE: + _set_space_override_mode(angular_damping_override_mode, (PhysicsServer2D::AreaSpaceOverrideMode)(int)p_value); + break; case PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP: angular_damp = p_value; break; @@ -162,6 +171,8 @@ void GodotArea2D::set_param(PhysicsServer2D::AreaParameter p_param, const Varian Variant GodotArea2D::get_param(PhysicsServer2D::AreaParameter p_param) const { switch (p_param) { + case PhysicsServer2D::AREA_PARAM_GRAVITY_OVERRIDE_MODE: + return gravity_override_mode; case PhysicsServer2D::AREA_PARAM_GRAVITY: return gravity; case PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR: @@ -172,8 +183,12 @@ Variant GodotArea2D::get_param(PhysicsServer2D::AreaParameter p_param) const { return gravity_distance_scale; case PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_ATTENUATION: return point_attenuation; + case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE: + return linear_damping_override_mode; case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP: return linear_damp; + case PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE: + return angular_damping_override_mode; case PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP: return angular_damp; case PhysicsServer2D::AREA_PARAM_PRIORITY: @@ -198,6 +213,7 @@ void GodotArea2D::set_monitorable(bool p_monitorable) { monitorable = p_monitorable; _set_static(!monitorable); + _shapes_changed(); } void GodotArea2D::call_queries() { diff --git a/servers/physics_2d/godot_area_2d.h b/servers/physics_2d/godot_area_2d.h index 13b3ce1bf2..699c1c1bc8 100644 --- a/servers/physics_2d/godot_area_2d.h +++ b/servers/physics_2d/godot_area_2d.h @@ -41,7 +41,10 @@ class GodotBody2D; class GodotConstraint2D; class GodotArea2D : public GodotCollisionObject2D { - PhysicsServer2D::AreaSpaceOverrideMode space_override_mode = PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED; + PhysicsServer2D::AreaSpaceOverrideMode gravity_override_mode = PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED; + PhysicsServer2D::AreaSpaceOverrideMode linear_damping_override_mode = PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED; + PhysicsServer2D::AreaSpaceOverrideMode angular_damping_override_mode = PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED; + real_t gravity = 9.80665; Vector2 gravity_vector = Vector2(0, -1); bool gravity_is_point = false; @@ -96,6 +99,8 @@ class GodotArea2D : public GodotCollisionObject2D { virtual void _shapes_changed(); void _queue_monitor_update(); + void _set_space_override_mode(PhysicsServer2D::AreaSpaceOverrideMode &r_mode, PhysicsServer2D::AreaSpaceOverrideMode p_new_mode); + public: void set_monitor_callback(const Callable &p_callback); _FORCE_INLINE_ bool has_monitor_callback() const { return !monitor_callback.is_null(); } @@ -112,9 +117,6 @@ public: void set_param(PhysicsServer2D::AreaParameter p_param, const Variant &p_value); Variant get_param(PhysicsServer2D::AreaParameter p_param) const; - void set_space_override_mode(PhysicsServer2D::AreaSpaceOverrideMode p_mode); - PhysicsServer2D::AreaSpaceOverrideMode get_space_override_mode() const { return space_override_mode; } - _FORCE_INLINE_ void set_gravity(real_t p_gravity) { gravity = p_gravity; } _FORCE_INLINE_ real_t get_gravity() const { return gravity; } diff --git a/servers/physics_2d/godot_area_pair_2d.cpp b/servers/physics_2d/godot_area_pair_2d.cpp index fdb95aa262..bde22aab11 100644 --- a/servers/physics_2d/godot_area_pair_2d.cpp +++ b/servers/physics_2d/godot_area_pair_2d.cpp @@ -38,10 +38,18 @@ bool GodotAreaPair2D::setup(real_t p_step) { } process_collision = false; + has_space_override = false; if (result != colliding) { - if (area->get_space_override_mode() != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) { - process_collision = true; - } else if (area->has_monitor_callback()) { + if ((int)area->get_param(PhysicsServer2D::AREA_PARAM_GRAVITY_OVERRIDE_MODE) != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) { + has_space_override = true; + } else if ((int)area->get_param(PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE) != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) { + has_space_override = true; + } else if ((int)area->get_param(PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE) != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) { + has_space_override = true; + } + process_collision = has_space_override; + + if (area->has_monitor_callback()) { process_collision = true; } @@ -57,7 +65,7 @@ bool GodotAreaPair2D::pre_solve(real_t p_step) { } if (colliding) { - if (area->get_space_override_mode() != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) { + if (has_space_override) { body->add_area(area); } @@ -65,7 +73,7 @@ bool GodotAreaPair2D::pre_solve(real_t p_step) { area->add_body_to_query(body, body_shape, area_shape); } } else { - if (area->get_space_override_mode() != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) { + if (has_space_override) { body->remove_area(area); } @@ -95,7 +103,7 @@ GodotAreaPair2D::GodotAreaPair2D(GodotBody2D *p_body, int p_body_shape, GodotAre GodotAreaPair2D::~GodotAreaPair2D() { if (colliding) { - if (area->get_space_override_mode() != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) { + if (has_space_override) { body->remove_area(area); } if (area->has_monitor_callback()) { @@ -120,7 +128,7 @@ bool GodotArea2Pair2D::setup(real_t p_step) { process_collision_a = false; if (result_a != colliding_a) { - if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) { + if (area_a->has_area_monitor_callback() && area_b_monitorable) { process_collision_a = true; process_collision = true; } @@ -129,7 +137,7 @@ bool GodotArea2Pair2D::setup(real_t p_step) { process_collision_b = false; if (result_b != colliding_b) { - if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) { + if (area_b->has_area_monitor_callback() && area_a_monitorable) { process_collision_b = true; process_collision = true; } @@ -168,19 +176,21 @@ GodotArea2Pair2D::GodotArea2Pair2D(GodotArea2D *p_area_a, int p_shape_a, GodotAr area_b = p_area_b; shape_a = p_shape_a; shape_b = p_shape_b; + area_a_monitorable = area_a->is_monitorable(); + area_b_monitorable = area_b->is_monitorable(); area_a->add_constraint(this); area_b->add_constraint(this); } GodotArea2Pair2D::~GodotArea2Pair2D() { if (colliding_a) { - if (area_a->has_area_monitor_callback()) { + if (area_a->has_area_monitor_callback() && area_b_monitorable) { area_a->remove_area_from_query(area_b, shape_b, shape_a); } } if (colliding_b) { - if (area_b->has_area_monitor_callback()) { + if (area_b->has_area_monitor_callback() && area_a_monitorable) { area_b->remove_area_from_query(area_a, shape_a, shape_b); } } diff --git a/servers/physics_2d/godot_area_pair_2d.h b/servers/physics_2d/godot_area_pair_2d.h index 7a9677f714..f1290a27d0 100644 --- a/servers/physics_2d/godot_area_pair_2d.h +++ b/servers/physics_2d/godot_area_pair_2d.h @@ -41,6 +41,7 @@ class GodotAreaPair2D : public GodotConstraint2D { int body_shape = 0; int area_shape = 0; bool colliding = false; + bool has_space_override = false; bool process_collision = false; public: @@ -61,6 +62,8 @@ class GodotArea2Pair2D : public GodotConstraint2D { bool colliding_b = false; bool process_collision_a = false; bool process_collision_b = false; + bool area_a_monitorable; + bool area_b_monitorable; public: virtual bool setup(real_t p_step) override; diff --git a/servers/physics_2d/godot_body_2d.cpp b/servers/physics_2d/godot_body_2d.cpp index 442c580920..44da5d4f3b 100644 --- a/servers/physics_2d/godot_body_2d.cpp +++ b/servers/physics_2d/godot_body_2d.cpp @@ -185,6 +185,9 @@ void GodotBody2D::set_param(PhysicsServer2D::BodyParameter p_param, const Varian _update_transform_dependent(); } break; case PhysicsServer2D::BODY_PARAM_GRAVITY_SCALE: { + if (Math::is_zero_approx(gravity_scale)) { + wakeup(); + } gravity_scale = p_value; } break; case PhysicsServer2D::BODY_PARAM_LINEAR_DAMP_MODE: { @@ -410,15 +413,6 @@ void GodotBody2D::set_space(GodotSpace2D *p_space) { } } -void GodotBody2D::_compute_area_gravity_and_damping(const GodotArea2D *p_area) { - Vector2 area_gravity; - p_area->compute_gravity(get_transform().get_origin(), area_gravity); - gravity += area_gravity; - - total_linear_damp += p_area->get_linear_damp(); - total_angular_damp += p_area->get_angular_damp(); -} - void GodotBody2D::_update_transform_dependent() { center_of_mass = get_transform().basis_xform(center_of_mass_local); } @@ -428,8 +422,16 @@ void GodotBody2D::integrate_forces(real_t p_step) { return; } + ERR_FAIL_COND(!get_space()); + int ac = areas.size(); + + bool gravity_done = false; + bool linear_damp_done = false; + bool angular_damp_done = false; + bool stopped = false; + gravity = Vector2(0, 0); total_linear_damp = 0.0; @@ -440,33 +442,89 @@ void GodotBody2D::integrate_forces(real_t p_step) { areas.sort(); const AreaCMP *aa = &areas[0]; for (int i = ac - 1; i >= 0 && !stopped; i--) { - PhysicsServer2D::AreaSpaceOverrideMode mode = aa[i].area->get_space_override_mode(); - switch (mode) { - case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE: - case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { - _compute_area_gravity_and_damping(aa[i].area); - stopped = mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; - } break; - case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE: - case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { - gravity = Vector2(0, 0); - total_linear_damp = 0.0; - total_angular_damp = 0.0; - _compute_area_gravity_and_damping(aa[i].area); - stopped = mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE; - } break; - default: { + if (!gravity_done) { + PhysicsServer2D::AreaSpaceOverrideMode area_gravity_mode = (PhysicsServer2D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer2D::AREA_PARAM_GRAVITY_OVERRIDE_MODE); + if (area_gravity_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) { + Vector2 area_gravity; + aa[i].area->compute_gravity(get_transform().get_origin(), area_gravity); + switch (area_gravity_mode) { + case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE: + case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { + gravity += area_gravity; + gravity_done = area_gravity_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; + } break; + case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE: + case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { + gravity = area_gravity; + gravity_done = area_gravity_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE; + } break; + default: { + } + } } } + if (!linear_damp_done) { + PhysicsServer2D::AreaSpaceOverrideMode area_linear_damp_mode = (PhysicsServer2D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE); + if (area_linear_damp_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) { + real_t area_linear_damp = aa[i].area->get_linear_damp(); + switch (area_linear_damp_mode) { + case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE: + case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { + total_linear_damp += area_linear_damp; + linear_damp_done = area_linear_damp_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; + } break; + case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE: + case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { + total_linear_damp = area_linear_damp; + linear_damp_done = area_linear_damp_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE; + } break; + default: { + } + } + } + } + if (!angular_damp_done) { + PhysicsServer2D::AreaSpaceOverrideMode area_angular_damp_mode = (PhysicsServer2D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE); + if (area_angular_damp_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) { + real_t area_angular_damp = aa[i].area->get_angular_damp(); + switch (area_angular_damp_mode) { + case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE: + case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { + total_angular_damp += area_angular_damp; + angular_damp_done = area_angular_damp_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; + } break; + case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE: + case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { + total_angular_damp = area_angular_damp; + angular_damp_done = area_angular_damp_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE; + } break; + default: { + } + } + } + } + stopped = gravity_done && linear_damp_done && angular_damp_done; } } - // Override linear damping with body's value. + // Add default gravity and damping from space area. if (!stopped) { - GodotArea2D *def_area = get_space()->get_default_area(); - ERR_FAIL_COND(!def_area); + GodotArea2D *default_area = get_space()->get_default_area(); + ERR_FAIL_COND(!default_area); - _compute_area_gravity_and_damping(def_area); + if (!gravity_done) { + Vector2 default_gravity; + default_area->compute_gravity(get_transform().get_origin(), default_gravity); + gravity += default_gravity; + } + + if (!linear_damp_done) { + total_linear_damp += default_area->get_linear_damp(); + } + + if (!angular_damp_done) { + total_angular_damp += default_area->get_angular_damp(); + } } // Override linear damping with body's value. @@ -491,6 +549,9 @@ void GodotBody2D::integrate_forces(real_t p_step) { gravity *= gravity_scale; + prev_linear_velocity = linear_velocity; + prev_angular_velocity = angular_velocity; + Vector2 motion; bool do_motion = false; diff --git a/servers/physics_2d/godot_body_2d.h b/servers/physics_2d/godot_body_2d.h index 7b11b50739..ba4c39737a 100644 --- a/servers/physics_2d/godot_body_2d.h +++ b/servers/physics_2d/godot_body_2d.h @@ -50,6 +50,9 @@ class GodotBody2D : public GodotCollisionObject2D { Vector2 linear_velocity; real_t angular_velocity = 0.0; + Vector2 prev_linear_velocity; + real_t prev_angular_velocity = 0.0; + Vector2 constant_linear_velocity; real_t constant_angular_velocity = 0.0; @@ -145,8 +148,6 @@ class GodotBody2D : public GodotCollisionObject2D { uint64_t island_step = 0; - void _compute_area_gravity_and_damping(const GodotArea2D *p_area); - void _update_transform_dependent(); friend class GodotPhysicsDirectBodyState2D; // i give up, too many functions to expose @@ -171,7 +172,7 @@ public: if (index > -1) { areas.write[index].refCount -= 1; if (areas[index].refCount < 1) { - areas.remove(index); + areas.remove_at(index); } } } @@ -211,6 +212,9 @@ public: _FORCE_INLINE_ void set_angular_velocity(real_t p_velocity) { angular_velocity = p_velocity; } _FORCE_INLINE_ real_t get_angular_velocity() const { return angular_velocity; } + _FORCE_INLINE_ Vector2 get_prev_linear_velocity() const { return prev_linear_velocity; } + _FORCE_INLINE_ real_t get_prev_angular_velocity() const { return prev_angular_velocity; } + _FORCE_INLINE_ void set_biased_linear_velocity(const Vector2 &p_velocity) { biased_linear_velocity = p_velocity; } _FORCE_INLINE_ Vector2 get_biased_linear_velocity() const { return biased_linear_velocity; } diff --git a/servers/physics_2d/godot_body_pair_2d.cpp b/servers/physics_2d/godot_body_pair_2d.cpp index 97eeefbfe6..67b0f21456 100644 --- a/servers/physics_2d/godot_body_pair_2d.cpp +++ b/servers/physics_2d/godot_body_pair_2d.cpp @@ -32,7 +32,6 @@ #include "godot_collision_solver_2d.h" #include "godot_space_2d.h" -#define POSITION_CORRECTION #define ACCUMULATE_IMPULSES void GodotBodyPair2D::_add_contact(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_self) { @@ -453,9 +452,9 @@ bool GodotBodyPair2D::pre_solve(real_t p_step) { c.bounce = combine_bounce(A, B); if (c.bounce) { - Vector2 crA(-A->get_angular_velocity() * c.rA.y, A->get_angular_velocity() * c.rA.x); - Vector2 crB(-B->get_angular_velocity() * c.rB.y, B->get_angular_velocity() * c.rB.x); - Vector2 dv = B->get_linear_velocity() + crB - A->get_linear_velocity() - crA; + Vector2 crA(-A->get_prev_angular_velocity() * c.rA.y, A->get_prev_angular_velocity() * c.rA.x); + Vector2 crB(-B->get_prev_angular_velocity() * c.rB.y, B->get_prev_angular_velocity() * c.rB.x); + Vector2 dv = B->get_prev_linear_velocity() + crB - A->get_prev_linear_velocity() - crA; c.bounce = c.bounce * dv.dot(c.normal); } diff --git a/servers/physics_2d/godot_collision_object_2d.cpp b/servers/physics_2d/godot_collision_object_2d.cpp index 3d4ebbedcd..719d9c874a 100644 --- a/servers/physics_2d/godot_collision_object_2d.cpp +++ b/servers/physics_2d/godot_collision_object_2d.cpp @@ -121,7 +121,7 @@ void GodotCollisionObject2D::remove_shape(int p_index) { shapes.write[i].bpid = 0; } shapes[p_index].shape->remove_owner(this); - shapes.remove(p_index); + shapes.remove_at(p_index); if (!pending_shape_update_list.in_list()) { GodotPhysicsServer2D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list); diff --git a/servers/physics_2d/godot_physics_server_2d.cpp b/servers/physics_2d/godot_physics_server_2d.cpp index cf66b80076..8ac27077fc 100644 --- a/servers/physics_2d/godot_physics_server_2d.cpp +++ b/servers/physics_2d/godot_physics_server_2d.cpp @@ -289,7 +289,7 @@ RID GodotPhysicsServer2D::area_create() { RID rid = area_owner.make_rid(area); area->set_self(rid); return rid; -}; +} void GodotPhysicsServer2D::area_set_space(RID p_area, RID p_space) { GodotArea2D *area = area_owner.get_or_null(p_area); @@ -307,7 +307,7 @@ void GodotPhysicsServer2D::area_set_space(RID p_area, RID p_space) { area->clear_constraints(); area->set_space(space); -}; +} RID GodotPhysicsServer2D::area_get_space(RID p_area) const { GodotArea2D *area = area_owner.get_or_null(p_area); @@ -318,20 +318,6 @@ RID GodotPhysicsServer2D::area_get_space(RID p_area) const { return RID(); } return space->get_self(); -}; - -void GodotPhysicsServer2D::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) { - GodotArea2D *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - area->set_space_override_mode(p_mode); -} - -PhysicsServer2D::AreaSpaceOverrideMode GodotPhysicsServer2D::area_get_space_override_mode(RID p_area) const { - const GodotArea2D *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND_V(!area, AREA_SPACE_OVERRIDE_DISABLED); - - return area->get_space_override_mode(); } void GodotPhysicsServer2D::area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform, bool p_disabled) { @@ -963,10 +949,17 @@ bool GodotPhysicsServer2D::body_test_motion(RID p_body, const MotionParameters & PhysicsDirectBodyState2D *GodotPhysicsServer2D::body_get_direct_state(RID p_body) { ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification."); + if (!body_owner.owns(p_body)) { + return nullptr; + } + GodotBody2D *body = body_owner.get_or_null(p_body); ERR_FAIL_COND_V(!body, nullptr); - ERR_FAIL_COND_V(!body->get_space(), nullptr); + if (!body->get_space()) { + return nullptr; + } + ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification."); return body->get_direct_state(); diff --git a/servers/physics_2d/godot_physics_server_2d.h b/servers/physics_2d/godot_physics_server_2d.h index b03d78a1de..1f544fee72 100644 --- a/servers/physics_2d/godot_physics_server_2d.h +++ b/servers/physics_2d/godot_physics_server_2d.h @@ -124,9 +124,6 @@ public: virtual RID area_create() override; - virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) override; - virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const override; - virtual void area_set_space(RID p_area, RID p_space) override; virtual RID area_get_space(RID p_area) const override; diff --git a/servers/physics_2d/godot_space_2d.cpp b/servers/physics_2d/godot_space_2d.cpp index 5c189aa06a..7a5eb26bb3 100644 --- a/servers/physics_2d/godot_space_2d.cpp +++ b/servers/physics_2d/godot_space_2d.cpp @@ -153,6 +153,22 @@ bool GodotPhysicsDirectSpaceState2D::intersect_ray(const RayParameters &p_parame Vector2 shape_point, shape_normal; + if (shape->contains_point(local_from)) { + if (p_parameters.hit_from_inside) { + // Hit shape at starting point. + min_d = 0; + res_point = local_from; + res_normal = Vector2(); + res_shape = shape_idx; + res_obj = col_obj; + collided = true; + break; + } else { + // Ignore shape when starting inside. + continue; + } + } + if (shape->intersect_segment(local_from, local_to, shape_point, shape_normal)) { Transform2D xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); shape_point = xform.xform(shape_point); @@ -423,8 +439,6 @@ bool GodotPhysicsDirectSpaceState2D::rest_info(const ShapeParameters &p_paramete GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid); ERR_FAIL_COND_V(!shape, 0); - real_t min_contact_depth = p_parameters.margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR; - Rect2 aabb = p_parameters.transform.xform(shape->get_aabb()); aabb = aabb.merge(Rect2(aabb.position + p_parameters.motion, aabb.size)); //motion aabb = aabb.grow(p_parameters.margin); @@ -432,10 +446,11 @@ bool GodotPhysicsDirectSpaceState2D::rest_info(const ShapeParameters &p_paramete int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); _RestCallbackData2D rcd; - rcd.best_len = 0; - rcd.best_object = nullptr; - rcd.best_shape = 0; - rcd.min_allowed_depth = min_contact_depth; + + // Allowed depth can't be lower than motion length, in order to handle contacts at low speed. + real_t motion_length = p_parameters.motion.length(); + real_t min_contact_depth = p_parameters.margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR; + rcd.min_allowed_depth = MIN(motion_length, min_contact_depth); for (int i = 0; i < amount; i++) { if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { @@ -863,9 +878,6 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D:: ugt.elements[2] += p_parameters.motion * unsafe; _RestCallbackData2D rcd; - rcd.best_len = 0; - rcd.best_object = nullptr; - rcd.best_shape = 0; // Allowed depth can't be lower than motion length, in order to handle contacts at low speed. rcd.min_allowed_depth = MIN(motion_length, min_contact_depth); diff --git a/servers/physics_2d/godot_step_2d.cpp b/servers/physics_2d/godot_step_2d.cpp index 84ec0e3c63..00d11acdab 100644 --- a/servers/physics_2d/godot_step_2d.cpp +++ b/servers/physics_2d/godot_step_2d.cpp @@ -152,6 +152,9 @@ void GodotStep2D::step(GodotSpace2D *p_space, real_t p_delta, int p_iterations) p_space->set_active_objects(active_count); + // Update the broadphase to register collision pairs. + p_space->update(); + { //profile profile_endtime = OS::get_singleton()->get_ticks_usec(); p_space->set_elapsed_time(GodotSpace2D::ELAPSED_TIME_INTEGRATE_FORCES, profile_endtime - profile_begtime); @@ -286,7 +289,6 @@ void GodotStep2D::step(GodotSpace2D *p_space, real_t p_delta, int p_iterations) all_constraints.clear(); - p_space->update(); p_space->unlock(); _step++; } diff --git a/servers/physics_3d/godot_area_3d.cpp b/servers/physics_3d/godot_area_3d.cpp index 973fc50968..d4e14b8d85 100644 --- a/servers/physics_3d/godot_area_3d.cpp +++ b/servers/physics_3d/godot_area_3d.cpp @@ -128,18 +128,21 @@ void GodotArea3D::set_area_monitor_callback(const Callable &p_callback) { } } -void GodotArea3D::set_space_override_mode(PhysicsServer3D::AreaSpaceOverrideMode p_mode) { - bool do_override = p_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED; - if (do_override == (space_override_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED)) { +void GodotArea3D::_set_space_override_mode(PhysicsServer3D::AreaSpaceOverrideMode &r_mode, PhysicsServer3D::AreaSpaceOverrideMode p_new_mode) { + bool do_override = p_new_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED; + if (do_override == (r_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED)) { return; } _unregister_shapes(); - space_override_mode = p_mode; + r_mode = p_new_mode; _shape_changed(); } void GodotArea3D::set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value) { switch (p_param) { + case PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE: + _set_space_override_mode(gravity_override_mode, (PhysicsServer3D::AreaSpaceOverrideMode)(int)p_value); + break; case PhysicsServer3D::AREA_PARAM_GRAVITY: gravity = p_value; break; @@ -155,9 +158,15 @@ void GodotArea3D::set_param(PhysicsServer3D::AreaParameter p_param, const Varian case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_ATTENUATION: point_attenuation = p_value; break; + case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE: + _set_space_override_mode(linear_damping_override_mode, (PhysicsServer3D::AreaSpaceOverrideMode)(int)p_value); + break; case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP: linear_damp = p_value; break; + case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE: + _set_space_override_mode(angular_damping_override_mode, (PhysicsServer3D::AreaSpaceOverrideMode)(int)p_value); + break; case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP: angular_damp = p_value; break; @@ -183,6 +192,8 @@ void GodotArea3D::set_param(PhysicsServer3D::AreaParameter p_param, const Varian Variant GodotArea3D::get_param(PhysicsServer3D::AreaParameter p_param) const { switch (p_param) { + case PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE: + return gravity_override_mode; case PhysicsServer3D::AREA_PARAM_GRAVITY: return gravity; case PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR: @@ -193,8 +204,12 @@ Variant GodotArea3D::get_param(PhysicsServer3D::AreaParameter p_param) const { return gravity_distance_scale; case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_ATTENUATION: return point_attenuation; + case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE: + return linear_damping_override_mode; case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP: return linear_damp; + case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE: + return angular_damping_override_mode; case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP: return angular_damp; case PhysicsServer3D::AREA_PARAM_PRIORITY: @@ -227,6 +242,7 @@ void GodotArea3D::set_monitorable(bool p_monitorable) { monitorable = p_monitorable; _set_static(!monitorable); + _shapes_changed(); } void GodotArea3D::call_queries() { diff --git a/servers/physics_3d/godot_area_3d.h b/servers/physics_3d/godot_area_3d.h index b02fa1d5b9..0dcf89b2b4 100644 --- a/servers/physics_3d/godot_area_3d.h +++ b/servers/physics_3d/godot_area_3d.h @@ -42,7 +42,10 @@ class GodotSoftBody3D; class GodotConstraint3D; class GodotArea3D : public GodotCollisionObject3D { - PhysicsServer3D::AreaSpaceOverrideMode space_override_mode = PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED; + PhysicsServer3D::AreaSpaceOverrideMode gravity_override_mode = PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED; + PhysicsServer3D::AreaSpaceOverrideMode linear_damping_override_mode = PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED; + PhysicsServer3D::AreaSpaceOverrideMode angular_damping_override_mode = PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED; + real_t gravity = 9.80665; Vector3 gravity_vector = Vector3(0, -1, 0); bool gravity_is_point = false; @@ -102,6 +105,8 @@ class GodotArea3D : public GodotCollisionObject3D { virtual void _shapes_changed(); void _queue_monitor_update(); + void _set_space_override_mode(PhysicsServer3D::AreaSpaceOverrideMode &r_mode, PhysicsServer3D::AreaSpaceOverrideMode p_new_mode); + public: void set_monitor_callback(const Callable &p_callback); _FORCE_INLINE_ bool has_monitor_callback() const { return !monitor_callback.is_null(); } @@ -121,9 +126,6 @@ public: void set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value); Variant get_param(PhysicsServer3D::AreaParameter p_param) const; - void set_space_override_mode(PhysicsServer3D::AreaSpaceOverrideMode p_mode); - PhysicsServer3D::AreaSpaceOverrideMode get_space_override_mode() const { return space_override_mode; } - _FORCE_INLINE_ void set_gravity(real_t p_gravity) { gravity = p_gravity; } _FORCE_INLINE_ real_t get_gravity() const { return gravity; } diff --git a/servers/physics_3d/godot_area_pair_3d.cpp b/servers/physics_3d/godot_area_pair_3d.cpp index 7453153de6..58188565e3 100644 --- a/servers/physics_3d/godot_area_pair_3d.cpp +++ b/servers/physics_3d/godot_area_pair_3d.cpp @@ -39,10 +39,18 @@ bool GodotAreaPair3D::setup(real_t p_step) { } process_collision = false; + has_space_override = false; if (result != colliding) { - if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { - process_collision = true; - } else if (area->has_monitor_callback()) { + if ((int)area->get_param(PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE) != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + has_space_override = true; + } else if ((int)area->get_param(PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE) != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + has_space_override = true; + } else if ((int)area->get_param(PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE) != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + has_space_override = true; + } + process_collision = has_space_override; + + if (area->has_monitor_callback()) { process_collision = true; } @@ -58,7 +66,7 @@ bool GodotAreaPair3D::pre_solve(real_t p_step) { } if (colliding) { - if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + if (has_space_override) { body->add_area(area); } @@ -66,7 +74,7 @@ bool GodotAreaPair3D::pre_solve(real_t p_step) { area->add_body_to_query(body, body_shape, area_shape); } } else { - if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + if (has_space_override) { body->remove_area(area); } @@ -96,7 +104,7 @@ GodotAreaPair3D::GodotAreaPair3D(GodotBody3D *p_body, int p_body_shape, GodotAre GodotAreaPair3D::~GodotAreaPair3D() { if (colliding) { - if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + if (has_space_override) { body->remove_area(area); } if (area->has_monitor_callback()) { @@ -121,7 +129,7 @@ bool GodotArea2Pair3D::setup(real_t p_step) { process_collision_a = false; if (result_a != colliding_a) { - if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) { + if (area_a->has_area_monitor_callback() && area_b_monitorable) { process_collision_a = true; process_collision = true; } @@ -130,7 +138,7 @@ bool GodotArea2Pair3D::setup(real_t p_step) { process_collision_b = false; if (result_b != colliding_b) { - if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) { + if (area_b->has_area_monitor_callback() && area_a_monitorable) { process_collision_b = true; process_collision = true; } @@ -169,19 +177,21 @@ GodotArea2Pair3D::GodotArea2Pair3D(GodotArea3D *p_area_a, int p_shape_a, GodotAr area_b = p_area_b; shape_a = p_shape_a; shape_b = p_shape_b; + area_a_monitorable = area_a->is_monitorable(); + area_b_monitorable = area_b->is_monitorable(); area_a->add_constraint(this); area_b->add_constraint(this); } GodotArea2Pair3D::~GodotArea2Pair3D() { if (colliding_a) { - if (area_a->has_area_monitor_callback()) { + if (area_a->has_area_monitor_callback() && area_b_monitorable) { area_a->remove_area_from_query(area_b, shape_b, shape_a); } } if (colliding_b) { - if (area_b->has_area_monitor_callback()) { + if (area_b->has_area_monitor_callback() && area_a_monitorable) { area_b->remove_area_from_query(area_a, shape_a, shape_b); } } @@ -207,10 +217,15 @@ bool GodotAreaSoftBodyPair3D::setup(real_t p_step) { } process_collision = false; + has_space_override = false; if (result != colliding) { - if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { - process_collision = true; - } else if (area->has_monitor_callback()) { + if ((int)area->get_param(PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE) != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + has_space_override = true; + } else if (area->get_wind_force_magnitude() > CMP_EPSILON) { + has_space_override = true; + } + + if (area->has_monitor_callback()) { process_collision = true; } @@ -226,7 +241,7 @@ bool GodotAreaSoftBodyPair3D::pre_solve(real_t p_step) { } if (colliding) { - if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + if (has_space_override) { soft_body->add_area(area); } @@ -234,7 +249,7 @@ bool GodotAreaSoftBodyPair3D::pre_solve(real_t p_step) { area->add_soft_body_to_query(soft_body, soft_body_shape, area_shape); } } else { - if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + if (has_space_override) { soft_body->remove_area(area); } @@ -261,7 +276,7 @@ GodotAreaSoftBodyPair3D::GodotAreaSoftBodyPair3D(GodotSoftBody3D *p_soft_body, i GodotAreaSoftBodyPair3D::~GodotAreaSoftBodyPair3D() { if (colliding) { - if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + if (has_space_override) { soft_body->remove_area(area); } if (area->has_monitor_callback()) { diff --git a/servers/physics_3d/godot_area_pair_3d.h b/servers/physics_3d/godot_area_pair_3d.h index f55c03be03..4237e7722e 100644 --- a/servers/physics_3d/godot_area_pair_3d.h +++ b/servers/physics_3d/godot_area_pair_3d.h @@ -43,6 +43,7 @@ class GodotAreaPair3D : public GodotConstraint3D { int area_shape; bool colliding = false; bool process_collision = false; + bool has_space_override = false; public: virtual bool setup(real_t p_step) override; @@ -62,6 +63,8 @@ class GodotArea2Pair3D : public GodotConstraint3D { bool colliding_b = false; bool process_collision_a = false; bool process_collision_b = false; + bool area_a_monitorable; + bool area_b_monitorable; public: virtual bool setup(real_t p_step) override; @@ -79,6 +82,7 @@ class GodotAreaSoftBodyPair3D : public GodotConstraint3D { int area_shape; bool colliding = false; bool process_collision = false; + bool has_space_override = false; public: virtual bool setup(real_t p_step) override; diff --git a/servers/physics_3d/godot_body_3d.cpp b/servers/physics_3d/godot_body_3d.cpp index acf60d61c2..d5098a2a5f 100644 --- a/servers/physics_3d/godot_body_3d.cpp +++ b/servers/physics_3d/godot_body_3d.cpp @@ -227,6 +227,9 @@ void GodotBody3D::set_param(PhysicsServer3D::BodyParameter p_param, const Varian _update_transform_dependent(); } break; case PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE: { + if (Math::is_zero_approx(gravity_scale)) { + wakeup(); + } gravity_scale = p_value; } break; case PhysicsServer3D::BODY_PARAM_LINEAR_DAMP_MODE: { @@ -457,15 +460,6 @@ void GodotBody3D::set_space(GodotSpace3D *p_space) { } } -void GodotBody3D::_compute_area_gravity_and_damping(const GodotArea3D *p_area) { - Vector3 area_gravity; - p_area->compute_gravity(get_transform().get_origin(), area_gravity); - gravity += area_gravity; - - total_linear_damp += p_area->get_linear_damp(); - total_angular_damp += p_area->get_angular_damp(); -} - void GodotBody3D::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool lock) { if (lock) { locked_axis |= p_axis; @@ -483,8 +477,16 @@ void GodotBody3D::integrate_forces(real_t p_step) { return; } + ERR_FAIL_COND(!get_space()); + int ac = areas.size(); + + bool gravity_done = false; + bool linear_damp_done = false; + bool angular_damp_done = false; + bool stopped = false; + gravity = Vector3(0, 0, 0); total_linear_damp = 0.0; @@ -495,33 +497,89 @@ void GodotBody3D::integrate_forces(real_t p_step) { areas.sort(); const AreaCMP *aa = &areas[0]; for (int i = ac - 1; i >= 0 && !stopped; i--) { - PhysicsServer3D::AreaSpaceOverrideMode mode = aa[i].area->get_space_override_mode(); - switch (mode) { - case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE: - case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { - _compute_area_gravity_and_damping(aa[i].area); - stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; - } break; - case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE: - case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { - gravity = Vector3(0, 0, 0); - total_linear_damp = 0.0; - total_angular_damp = 0.0; - _compute_area_gravity_and_damping(aa[i].area); - stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE; - } break; - default: { + if (!gravity_done) { + PhysicsServer3D::AreaSpaceOverrideMode area_gravity_mode = (PhysicsServer3D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE); + if (area_gravity_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + Vector3 area_gravity; + aa[i].area->compute_gravity(get_transform().get_origin(), area_gravity); + switch (area_gravity_mode) { + case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { + gravity += area_gravity; + gravity_done = area_gravity_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; + } break; + case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { + gravity = area_gravity; + gravity_done = area_gravity_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE; + } break; + default: { + } + } + } + } + if (!linear_damp_done) { + PhysicsServer3D::AreaSpaceOverrideMode area_linear_damp_mode = (PhysicsServer3D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE); + if (area_linear_damp_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + real_t area_linear_damp = aa[i].area->get_linear_damp(); + switch (area_linear_damp_mode) { + case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { + total_linear_damp += area_linear_damp; + linear_damp_done = area_linear_damp_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; + } break; + case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { + total_linear_damp = area_linear_damp; + linear_damp_done = area_linear_damp_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE; + } break; + default: { + } + } + } + } + if (!angular_damp_done) { + PhysicsServer3D::AreaSpaceOverrideMode area_angular_damp_mode = (PhysicsServer3D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE); + if (area_angular_damp_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + real_t area_angular_damp = aa[i].area->get_angular_damp(); + switch (area_angular_damp_mode) { + case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { + total_angular_damp += area_angular_damp; + angular_damp_done = area_angular_damp_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; + } break; + case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { + total_angular_damp = area_angular_damp; + angular_damp_done = area_angular_damp_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE; + } break; + default: { + } + } } } + stopped = gravity_done && linear_damp_done && angular_damp_done; } } // Add default gravity and damping from space area. if (!stopped) { - GodotArea3D *def_area = get_space()->get_default_area(); - ERR_FAIL_COND(!def_area); + GodotArea3D *default_area = get_space()->get_default_area(); + ERR_FAIL_COND(!default_area); - _compute_area_gravity_and_damping(def_area); + if (!gravity_done) { + Vector3 default_gravity; + default_area->compute_gravity(get_transform().get_origin(), default_gravity); + gravity += default_gravity; + } + + if (!linear_damp_done) { + total_linear_damp += default_area->get_linear_damp(); + } + + if (!angular_damp_done) { + total_angular_damp += default_area->get_angular_damp(); + } } // Override linear damping with body's value. @@ -546,6 +604,9 @@ void GodotBody3D::integrate_forces(real_t p_step) { gravity *= gravity_scale; + prev_linear_velocity = linear_velocity; + prev_angular_velocity = angular_velocity; + Vector3 motion; bool do_motion = false; diff --git a/servers/physics_3d/godot_body_3d.h b/servers/physics_3d/godot_body_3d.h index 7fc2f58168..6ea6d1fcaa 100644 --- a/servers/physics_3d/godot_body_3d.h +++ b/servers/physics_3d/godot_body_3d.h @@ -45,6 +45,9 @@ class GodotBody3D : public GodotCollisionObject3D { Vector3 linear_velocity; Vector3 angular_velocity; + Vector3 prev_linear_velocity; + Vector3 prev_angular_velocity; + Vector3 constant_linear_velocity; Vector3 constant_angular_velocity; @@ -139,8 +142,6 @@ class GodotBody3D : public GodotCollisionObject3D { uint64_t island_step = 0; - void _compute_area_gravity_and_damping(const GodotArea3D *p_area); - void _update_transform_dependent(); friend class GodotPhysicsDirectBodyState3D; // i give up, too many functions to expose @@ -165,7 +166,7 @@ public: if (index > -1) { areas.write[index].refCount -= 1; if (areas[index].refCount < 1) { - areas.remove(index); + areas.remove_at(index); } } } @@ -209,6 +210,9 @@ public: _FORCE_INLINE_ void set_angular_velocity(const Vector3 &p_velocity) { angular_velocity = p_velocity; } _FORCE_INLINE_ Vector3 get_angular_velocity() const { return angular_velocity; } + _FORCE_INLINE_ Vector3 get_prev_linear_velocity() const { return prev_linear_velocity; } + _FORCE_INLINE_ Vector3 get_prev_angular_velocity() const { return prev_angular_velocity; } + _FORCE_INLINE_ const Vector3 &get_biased_linear_velocity() const { return biased_linear_velocity; } _FORCE_INLINE_ const Vector3 &get_biased_angular_velocity() const { return biased_angular_velocity; } diff --git a/servers/physics_3d/godot_body_pair_3d.cpp b/servers/physics_3d/godot_body_pair_3d.cpp index f7d9ed9ee9..8a701466ed 100644 --- a/servers/physics_3d/godot_body_pair_3d.cpp +++ b/servers/physics_3d/godot_body_pair_3d.cpp @@ -35,18 +35,6 @@ #include "core/os/os.h" -/* -#define NO_ACCUMULATE_IMPULSES -#define NO_SPLIT_IMPULSES - -#define NO_FRICTION -*/ - -#define NO_TANGENTIALS -/* BODY PAIR */ - -//#define ALLOWED_PENETRATION 0.01 -#define RELAXATION_TIMESTEPS 3 #define MIN_VELOCITY 0.0001 #define MAX_BIAS_ROTATION (Math_PI / 8) @@ -191,7 +179,7 @@ bool GodotBodyPair3D::_test_ccd(real_t p_step, GodotBody3D *p_A, int p_shape_A, Vector3 local_to = from_inv.xform(to); Vector3 rpos, rnorm; - if (!p_B->get_shape(p_shape_B)->intersect_segment(local_from, local_to, rpos, rnorm)) { + if (!p_B->get_shape(p_shape_B)->intersect_segment(local_from, local_to, rpos, rnorm, true)) { return false; } @@ -370,10 +358,9 @@ bool GodotBodyPair3D::pre_solve(real_t p_step) { c.bounce = combine_bounce(A, B); if (c.bounce) { - Vector3 crA = A->get_angular_velocity().cross(c.rA); - Vector3 crB = B->get_angular_velocity().cross(c.rB); - Vector3 dv = B->get_linear_velocity() + crB - A->get_linear_velocity() - crA; - //normal impule + Vector3 crA = A->get_prev_angular_velocity().cross(c.rA); + Vector3 crB = B->get_prev_angular_velocity().cross(c.rB); + Vector3 dv = B->get_prev_linear_velocity() + crB - A->get_prev_linear_velocity() - crA; c.bounce = c.bounce * dv.dot(c.normal); } } diff --git a/servers/physics_3d/godot_collision_object_3d.cpp b/servers/physics_3d/godot_collision_object_3d.cpp index deb058b3ac..421291011b 100644 --- a/servers/physics_3d/godot_collision_object_3d.cpp +++ b/servers/physics_3d/godot_collision_object_3d.cpp @@ -118,7 +118,7 @@ void GodotCollisionObject3D::remove_shape(int p_index) { shapes.write[i].bpid = 0; } shapes[p_index].shape->remove_owner(this); - shapes.remove(p_index); + shapes.remove_at(p_index); if (!pending_shape_update_list.in_list()) { GodotPhysicsServer3D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list); diff --git a/servers/physics_3d/godot_collision_solver_3d.cpp b/servers/physics_3d/godot_collision_solver_3d.cpp index b9f2f7506b..540b16c6e3 100644 --- a/servers/physics_3d/godot_collision_solver_3d.cpp +++ b/servers/physics_3d/godot_collision_solver_3d.cpp @@ -102,7 +102,7 @@ bool GodotCollisionSolver3D::solve_separation_ray(const GodotShape3D *p_shape_A, to = ai.xform(to); Vector3 p, n; - if (!p_shape_B->intersect_segment(from, to, p, n)) { + if (!p_shape_B->intersect_segment(from, to, p, n, true)) { return false; } @@ -264,7 +264,7 @@ bool GodotCollisionSolver3D::solve_soft_body(const GodotShape3D *p_shape_A, cons local_aabb.size[i] = smax - smin; } - concave_shape_A->cull(local_aabb, soft_body_concave_callback, &query_cinfo); + concave_shape_A->cull(local_aabb, soft_body_concave_callback, &query_cinfo, true); } else { AABB shape_aabb = p_transform_A.xform(p_shape_A->get_aabb()); shape_aabb.grow_by(collision_margin); @@ -346,7 +346,7 @@ bool GodotCollisionSolver3D::solve_concave(const GodotShape3D *p_shape_A, const local_aabb.size[i] = smax - smin; } - concave_B->cull(local_aabb, concave_callback, &cinfo); + concave_B->cull(local_aabb, concave_callback, &cinfo, false); return cinfo.collided; } @@ -559,7 +559,7 @@ bool GodotCollisionSolver3D::solve_distance(const GodotShape3D *p_shape_A, const local_aabb.size[i] = smax - smin; } - concave_B->cull(local_aabb, concave_distance_callback, &cinfo); + concave_B->cull(local_aabb, concave_distance_callback, &cinfo, false); if (!cinfo.collided) { r_point_A = cinfo.close_A; r_point_B = cinfo.close_B; diff --git a/servers/physics_3d/godot_collision_solver_3d_sat.cpp b/servers/physics_3d/godot_collision_solver_3d_sat.cpp index 0790333f65..4faa07b6c9 100644 --- a/servers/physics_3d/godot_collision_solver_3d_sat.cpp +++ b/servers/physics_3d/godot_collision_solver_3d_sat.cpp @@ -36,6 +36,8 @@ #define fallback_collision_solver gjk_epa_calculate_penetration +#define _BACKFACE_NORMAL_THRESHOLD -0.0002 + // Cylinder SAT analytic methods and face-circle contact points for cylinder-trimesh and cylinder-box collision are based on ODE colliders. /* @@ -612,13 +614,14 @@ class SeparatorAxisTest { const Transform3D *transform_A = nullptr; const Transform3D *transform_B = nullptr; real_t best_depth = 1e15; - Vector3 best_axis; _CollectorCallback *callback = nullptr; real_t margin_A = 0.0; real_t margin_B = 0.0; Vector3 separator_axis; public: + Vector3 best_axis; + _FORCE_INLINE_ bool test_previous_axis() { if (callback && callback->prev_axis && *callback->prev_axis != Vector3()) { return test_axis(*callback->prev_axis); @@ -627,7 +630,7 @@ public: } } - _FORCE_INLINE_ bool test_axis(const Vector3 &p_axis, bool p_directional = false) { + _FORCE_INLINE_ bool test_axis(const Vector3 &p_axis) { Vector3 axis = p_axis; if (axis.is_equal_approx(Vector3())) { @@ -661,12 +664,7 @@ public: //use the smallest depth if (min_B < 0.0) { // could be +0.0, we don't want it to become -0.0 - if (p_directional) { - min_B = max_B; - axis = -axis; - } else { - min_B = -min_B; - } + min_B = -min_B; } if (max_B < min_B) { @@ -1014,7 +1012,7 @@ static void _collision_sphere_face(const GodotShape3D *p_a, const Transform3D &p Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized(); - if (!separator.test_axis(normal, !face_B->backface_collision)) { + if (!separator.test_axis(normal)) { return; } @@ -1041,6 +1039,17 @@ static void _collision_sphere_face(const GodotShape3D *p_a, const Transform3D &p } } + if (!face_B->backface_collision) { + if (separator.best_axis.dot(normal) < _BACKFACE_NORMAL_THRESHOLD) { + if (face_B->invert_backface_collision) { + separator.best_axis = separator.best_axis.bounce(normal); + } else { + // Just ignore backface collision. + return; + } + } + } + separator.generate_contacts(); } @@ -1486,7 +1495,7 @@ static void _collision_box_face(const GodotShape3D *p_a, const Transform3D &p_tr Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized(); - if (!separator.test_axis(normal, !face_B->backface_collision)) { + if (!separator.test_axis(normal)) { return; } @@ -1591,6 +1600,17 @@ static void _collision_box_face(const GodotShape3D *p_a, const Transform3D &p_tr } } + if (!face_B->backface_collision) { + if (separator.best_axis.dot(normal) < _BACKFACE_NORMAL_THRESHOLD) { + if (face_B->invert_backface_collision) { + separator.best_axis = separator.best_axis.bounce(normal); + } else { + // Just ignore backface collision. + return; + } + } + } + separator.generate_contacts(); } @@ -1802,7 +1822,7 @@ static void _collision_capsule_face(const GodotShape3D *p_a, const Transform3D & Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized(); - if (!separator.test_axis(normal, !face_B->backface_collision)) { + if (!separator.test_axis(normal)) { return; } @@ -1858,6 +1878,17 @@ static void _collision_capsule_face(const GodotShape3D *p_a, const Transform3D & } } + if (!face_B->backface_collision) { + if (separator.best_axis.dot(normal) < _BACKFACE_NORMAL_THRESHOLD) { + if (face_B->invert_backface_collision) { + separator.best_axis = separator.best_axis.bounce(normal); + } else { + // Just ignore backface collision. + return; + } + } + } + separator.generate_contacts(); } @@ -1952,7 +1983,7 @@ static void _collision_cylinder_face(const GodotShape3D *p_a, const Transform3D Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized(); // Face B normal. - if (!separator.test_axis(normal, !face_B->backface_collision)) { + if (!separator.test_axis(normal)) { return; } @@ -2034,6 +2065,17 @@ static void _collision_cylinder_face(const GodotShape3D *p_a, const Transform3D } } + if (!face_B->backface_collision) { + if (separator.best_axis.dot(normal) < _BACKFACE_NORMAL_THRESHOLD) { + if (face_B->invert_backface_collision) { + separator.best_axis = separator.best_axis.bounce(normal); + } else { + // Just ignore backface collision. + return; + } + } + } + separator.generate_contacts(); } @@ -2174,7 +2216,7 @@ static void _collision_convex_polygon_face(const GodotShape3D *p_a, const Transf Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized(); - if (!separator.test_axis(normal, !face_B->backface_collision)) { + if (!separator.test_axis(normal)) { return; } @@ -2266,6 +2308,17 @@ static void _collision_convex_polygon_face(const GodotShape3D *p_a, const Transf } } + if (!face_B->backface_collision) { + if (separator.best_axis.dot(normal) < _BACKFACE_NORMAL_THRESHOLD) { + if (face_B->invert_backface_collision) { + separator.best_axis = separator.best_axis.bounce(normal); + } else { + // Just ignore backface collision. + return; + } + } + } + separator.generate_contacts(); } diff --git a/servers/physics_3d/godot_physics_server_3d.cpp b/servers/physics_3d/godot_physics_server_3d.cpp index 73654939ca..9acae62382 100644 --- a/servers/physics_3d/godot_physics_server_3d.cpp +++ b/servers/physics_3d/godot_physics_server_3d.cpp @@ -219,7 +219,7 @@ RID GodotPhysicsServer3D::area_create() { RID rid = area_owner.make_rid(area); area->set_self(rid); return rid; -}; +} void GodotPhysicsServer3D::area_set_space(RID p_area, RID p_space) { GodotArea3D *area = area_owner.get_or_null(p_area); @@ -237,7 +237,7 @@ void GodotPhysicsServer3D::area_set_space(RID p_area, RID p_space) { area->clear_constraints(); area->set_space(space); -}; +} RID GodotPhysicsServer3D::area_get_space(RID p_area) const { GodotArea3D *area = area_owner.get_or_null(p_area); @@ -248,20 +248,6 @@ RID GodotPhysicsServer3D::area_get_space(RID p_area) const { return RID(); } return space->get_self(); -}; - -void GodotPhysicsServer3D::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) { - GodotArea3D *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - area->set_space_override_mode(p_mode); -} - -PhysicsServer3D::AreaSpaceOverrideMode GodotPhysicsServer3D::area_get_space_override_mode(RID p_area) const { - const GodotArea3D *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND_V(!area, AREA_SPACE_OVERRIDE_DISABLED); - - return area->get_space_override_mode(); } void GodotPhysicsServer3D::area_add_shape(RID p_area, RID p_shape, const Transform3D &p_transform, bool p_disabled) { @@ -881,10 +867,17 @@ bool GodotPhysicsServer3D::body_test_motion(RID p_body, const MotionParameters & PhysicsDirectBodyState3D *GodotPhysicsServer3D::body_get_direct_state(RID p_body) { ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification."); + if (!body_owner.owns(p_body)) { + return nullptr; + } + GodotBody3D *body = body_owner.get_or_null(p_body); ERR_FAIL_NULL_V(body, nullptr); - ERR_FAIL_NULL_V(body->get_space(), nullptr); + if (!body->get_space()) { + return nullptr; + } + ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification."); return body->get_direct_state(); diff --git a/servers/physics_3d/godot_physics_server_3d.h b/servers/physics_3d/godot_physics_server_3d.h index 4ddd10a4e0..f5c8e0f60d 100644 --- a/servers/physics_3d/godot_physics_server_3d.h +++ b/servers/physics_3d/godot_physics_server_3d.h @@ -122,9 +122,6 @@ public: virtual RID area_create() override; - virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) override; - virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const override; - virtual void area_set_space(RID p_area, RID p_space) override; virtual RID area_get_space(RID p_area) const override; diff --git a/servers/physics_3d/godot_shape_3d.cpp b/servers/physics_3d/godot_shape_3d.cpp index 4c12a5a948..5364a9833d 100644 --- a/servers/physics_3d/godot_shape_3d.cpp +++ b/servers/physics_3d/godot_shape_3d.cpp @@ -119,7 +119,7 @@ Vector3 GodotWorldBoundaryShape3D::get_support(const Vector3 &p_normal) const { return p_normal * 1e15; } -bool GodotWorldBoundaryShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotWorldBoundaryShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const { bool inters = plane.intersects_segment(p_begin, p_end, &r_result); if (inters) { r_normal = plane.normal; @@ -200,7 +200,7 @@ void GodotSeparationRayShape3D::get_supports(const Vector3 &p_normal, int p_max, } } -bool GodotSeparationRayShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotSeparationRayShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const { return false; //simply not possible } @@ -268,7 +268,7 @@ void GodotSphereShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector r_type = FEATURE_POINT; } -bool GodotSphereShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotSphereShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const { return Geometry3D::segment_intersects_sphere(p_begin, p_end, Vector3(), radius, &r_result, &r_normal); } @@ -410,7 +410,7 @@ void GodotBoxShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 * r_supports[0] = point; } -bool GodotBoxShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotBoxShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const { AABB aabb(-half_extents, half_extents * 2.0); return aabb.intersects_segment(p_begin, p_end, &r_result, &r_normal); @@ -430,7 +430,7 @@ Vector3 GodotBoxShape3D::get_closest_point_to(const Vector3 &p_point) const { if (outside == 1) { //use plane if only one side matches Vector3 n; - n[i] = SGN(p_point[i]); + n[i] = SIGN(p_point[i]); Plane p(n, half_extents[i]); min_point = p.project(p_point); @@ -546,7 +546,7 @@ void GodotCapsuleShape3D::get_supports(const Vector3 &p_normal, int p_max, Vecto } } -bool GodotCapsuleShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotCapsuleShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const { Vector3 norm = (p_end - p_begin).normalized(); real_t min_d = 1e20; @@ -761,7 +761,7 @@ void GodotCylinderShape3D::get_supports(const Vector3 &p_normal, int p_max, Vect } } -bool GodotCylinderShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotCylinderShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const { return Geometry3D::segment_intersects_cylinder(p_begin, p_end, height, radius, &r_result, &r_normal, 1); } @@ -954,7 +954,7 @@ void GodotConvexPolygonShape3D::get_supports(const Vector3 &p_normal, int p_max, r_type = FEATURE_POINT; } -bool GodotConvexPolygonShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotConvexPolygonShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const { const Geometry3D::MeshData::Face *faces = mesh.faces.ptr(); int fc = mesh.faces.size(); @@ -1188,12 +1188,12 @@ void GodotFaceShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 r_supports[0] = vertex[vert_support_idx]; } -bool GodotFaceShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotFaceShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const { bool c = Geometry3D::segment_intersects_triangle(p_begin, p_end, vertex[0], vertex[1], vertex[2], &r_result); if (c) { r_normal = Plane(vertex[0], vertex[1], vertex[2]).normal; if (r_normal.dot(p_end - p_begin) > 0) { - if (backface_collision) { + if (backface_collision && p_hit_back_faces) { r_normal = -r_normal; } else { c = false; @@ -1304,7 +1304,7 @@ void GodotConcavePolygonShape3D::_cull_segment(int p_idx, _SegmentCullParams *p_ Vector3 res; Vector3 normal; - if (face->intersect_segment(p_params->from, p_params->to, res, normal)) { + if (face->intersect_segment(p_params->from, p_params->to, res, normal, true)) { real_t d = p_params->dir.dot(res) - p_params->dir.dot(p_params->from); if ((d > 0) && (d < p_params->min_d)) { p_params->min_d = d; @@ -1323,7 +1323,7 @@ void GodotConcavePolygonShape3D::_cull_segment(int p_idx, _SegmentCullParams *p_ } } -bool GodotConcavePolygonShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotConcavePolygonShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const { if (faces.size() == 0) { return false; } @@ -1334,7 +1334,7 @@ bool GodotConcavePolygonShape3D::intersect_segment(const Vector3 &p_begin, const const BVH *br = bvh.ptr(); GodotFaceShape3D face; - face.backface_collision = backface_collision; + face.backface_collision = backface_collision && p_hit_back_faces; _SegmentCullParams params; params.from = p_begin; @@ -1401,7 +1401,7 @@ bool GodotConcavePolygonShape3D::_cull(int p_idx, _CullParams *p_params) const { return false; } -void GodotConcavePolygonShape3D::cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const { +void GodotConcavePolygonShape3D::cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata, bool p_invert_backface_collision) const { // make matrix local to concave if (faces.size() == 0) { return; @@ -1416,6 +1416,7 @@ void GodotConcavePolygonShape3D::cull(const AABB &p_local_aabb, QueryCallback p_ GodotFaceShape3D face; // use this to send in the callback face.backface_collision = backface_collision; + face.invert_backface_collision = p_invert_backface_collision; _CullParams params; params.aabb = local_aabb; @@ -1675,7 +1676,7 @@ struct _HeightmapGridCullState { _FORCE_INLINE_ bool _heightmap_face_cull_segment(_HeightmapSegmentCullParams &p_params) { Vector3 res; Vector3 normal; - if (p_params.face->intersect_segment(p_params.from, p_params.to, res, normal)) { + if (p_params.face->intersect_segment(p_params.from, p_params.to, res, normal, true)) { p_params.result = res; p_params.normal = normal; return true; @@ -1881,7 +1882,7 @@ bool GodotHeightMapShape3D::_intersect_grid_segment(ProcessFunction &p_process, return false; } -bool GodotHeightMapShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const { +bool GodotHeightMapShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal, bool p_hit_back_faces) const { if (heights.is_empty()) { return false; } @@ -1899,7 +1900,7 @@ bool GodotHeightMapShape3D::intersect_segment(const Vector3 &p_begin, const Vect // Simple case for rays that don't traverse the grid horizontally. // Just perform a test on the given cell. GodotFaceShape3D face; - face.backface_collision = false; + face.backface_collision = p_hit_back_faces; _HeightmapSegmentCullParams params; params.from = p_begin; @@ -1961,7 +1962,7 @@ void GodotHeightMapShape3D::_get_cell(const Vector3 &p_point, int &r_x, int &r_y r_z = (clamped_point.z < 0.0) ? (clamped_point.z - 0.5) : (clamped_point.z + 0.5); } -void GodotHeightMapShape3D::cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const { +void GodotHeightMapShape3D::cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata, bool p_invert_backface_collision) const { if (heights.is_empty()) { return; } @@ -1988,7 +1989,8 @@ void GodotHeightMapShape3D::cull(const AABB &p_local_aabb, QueryCallback p_callb int end_z = MIN(depth - 1, aabb_max[2]); GodotFaceShape3D face; - face.backface_collision = true; + face.backface_collision = !p_invert_backface_collision; + face.invert_backface_collision = p_invert_backface_collision; for (int z = start_z; z < end_z; z++) { for (int x = start_x; x < end_x; x++) { diff --git a/servers/physics_3d/godot_shape_3d.h b/servers/physics_3d/godot_shape_3d.h index 1bbcd903f7..43319510d4 100644 --- a/servers/physics_3d/godot_shape_3d.h +++ b/servers/physics_3d/godot_shape_3d.h @@ -80,7 +80,7 @@ public: virtual Vector3 get_support(const Vector3 &p_normal) const; virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const = 0; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const = 0; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const = 0; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal, bool p_hit_back_faces) const = 0; virtual bool intersect_point(const Vector3 &p_point) const = 0; virtual Vector3 get_moment_of_inertia(real_t p_mass) const = 0; @@ -107,7 +107,7 @@ public: // Returns true to stop the query. typedef bool (*QueryCallback)(void *p_userdata, GodotShape3D *p_convex); - virtual void cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const = 0; + virtual void cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata, bool p_invert_backface_collision) const = 0; GodotConcaveShape3D() {} }; @@ -126,7 +126,7 @@ public: virtual Vector3 get_support(const Vector3 &p_normal) const override; virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override { r_amount = 0; } - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override; virtual bool intersect_point(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; virtual Vector3 get_moment_of_inertia(real_t p_mass) const override; @@ -153,7 +153,7 @@ public: virtual Vector3 get_support(const Vector3 &p_normal) const override; virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override; virtual bool intersect_point(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; @@ -180,7 +180,7 @@ public: virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual Vector3 get_support(const Vector3 &p_normal) const override; virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override; virtual bool intersect_point(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; @@ -205,7 +205,7 @@ public: virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual Vector3 get_support(const Vector3 &p_normal) const override; virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override; virtual bool intersect_point(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; @@ -234,7 +234,7 @@ public: virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual Vector3 get_support(const Vector3 &p_normal) const override; virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override; virtual bool intersect_point(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; @@ -263,7 +263,7 @@ public: virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual Vector3 get_support(const Vector3 &p_normal) const override; virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override; virtual bool intersect_point(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; @@ -288,7 +288,7 @@ public: virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual Vector3 get_support(const Vector3 &p_normal) const override; virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override; virtual bool intersect_point(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; @@ -366,11 +366,11 @@ public: virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual Vector3 get_support(const Vector3 &p_normal) const override; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override; virtual bool intersect_point(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; - virtual void cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const override; + virtual void cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata, bool p_invert_backface_collision) const override; virtual Vector3 get_moment_of_inertia(real_t p_mass) const override; @@ -429,11 +429,11 @@ public: virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual Vector3 get_support(const Vector3 &p_normal) const override; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const override; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal, bool p_hit_back_faces) const override; virtual bool intersect_point(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; - virtual void cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const override; + virtual void cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata, bool p_invert_backface_collision) const override; virtual Vector3 get_moment_of_inertia(real_t p_mass) const override; @@ -448,6 +448,7 @@ struct GodotFaceShape3D : public GodotShape3D { Vector3 normal; //cache Vector3 vertex[3]; bool backface_collision = false; + bool invert_backface_collision = false; virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_CONCAVE_POLYGON; } @@ -456,7 +457,7 @@ struct GodotFaceShape3D : public GodotShape3D { virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual Vector3 get_support(const Vector3 &p_normal) const override; virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override; virtual bool intersect_point(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; @@ -495,7 +496,7 @@ struct GodotMotionShape3D : public GodotShape3D { } virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override { r_amount = 0; } - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override { return false; } + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override { return false; } virtual bool intersect_point(const Vector3 &p_point) const override { return false; } virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override { return p_point; } diff --git a/servers/physics_3d/godot_soft_body_3d.cpp b/servers/physics_3d/godot_soft_body_3d.cpp index 4b3e8cc0d9..43d4433302 100644 --- a/servers/physics_3d/godot_soft_body_3d.cpp +++ b/servers/physics_3d/godot_soft_body_3d.cpp @@ -374,7 +374,7 @@ void GodotSoftBody3D::unpin_vertex(int p_index) { uint32_t pinned_count = pinned_vertices.size(); for (uint32_t i = 0; i < pinned_count; ++i) { if (p_index == pinned_vertices[i]) { - pinned_vertices.remove(i); + pinned_vertices.remove_at(i); if (!soft_mesh.is_null()) { ERR_FAIL_COND(p_index >= (int)map_visual_to_physics.size()); @@ -917,9 +917,7 @@ void GodotSoftBody3D::add_velocity(const Vector3 &p_velocity) { } } -void GodotSoftBody3D::apply_forces(bool p_has_wind_forces) { - int ac = areas.size(); - +void GodotSoftBody3D::apply_forces(const LocalVector<GodotArea3D *> &p_wind_areas) { if (nodes.is_empty()) { return; } @@ -932,7 +930,6 @@ void GodotSoftBody3D::apply_forces(bool p_has_wind_forces) { // Iterate over faces (try not to iterate elsewhere if possible). for (i = 0, ni = faces.size(); i < ni; ++i) { - bool stopped = false; const Face &face = faces[i]; Vector3 wind_force(0, 0, 0); @@ -941,24 +938,10 @@ void GodotSoftBody3D::apply_forces(bool p_has_wind_forces) { volume += vec3_dot(face.n[0]->x - org, vec3_cross(face.n[1]->x - org, face.n[2]->x - org)); // Compute nodal forces from area winds. - if (ac && p_has_wind_forces) { - const AreaCMP *aa = &areas[0]; - for (j = ac - 1; j >= 0 && !stopped; j--) { - PhysicsServer3D::AreaSpaceOverrideMode mode = aa[j].area->get_space_override_mode(); - switch (mode) { - case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE: - case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { - wind_force += _compute_area_windforce(aa[j].area, &face); - stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; - } break; - case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE: - case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { - wind_force = _compute_area_windforce(aa[j].area, &face); - stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE; - } break; - default: { - } - } + int wind_area_count = p_wind_areas.size(); + if (wind_area_count > 0) { + for (j = 0; j < wind_area_count; j++) { + wind_force += _compute_area_windforce(p_wind_areas[j], &face); } for (j = 0; j < 3; j++) { @@ -981,12 +964,6 @@ void GodotSoftBody3D::apply_forces(bool p_has_wind_forces) { } } -void GodotSoftBody3D::_compute_area_gravity(const GodotArea3D *p_area) { - Vector3 area_gravity; - p_area->compute_gravity(get_transform().get_origin(), area_gravity); - gravity += area_gravity; -} - Vector3 GodotSoftBody3D::_compute_area_windforce(const GodotArea3D *p_area, const Face *p_face) { real_t wfm = p_area->get_wind_force_magnitude(); real_t waf = p_area->get_wind_attenuation_factor(); @@ -1004,44 +981,59 @@ void GodotSoftBody3D::predict_motion(real_t p_delta) { ERR_FAIL_COND(!get_space()); - GodotArea3D *def_area = get_space()->get_default_area(); - ERR_FAIL_COND(!def_area); - gravity = def_area->get_gravity_vector() * def_area->get_gravity(); + bool gravity_done = false; + Vector3 gravity; - int ac = areas.size(); - bool stopped = false; - bool has_wind_forces = false; + LocalVector<GodotArea3D *> wind_areas; + int ac = areas.size(); if (ac) { areas.sort(); const AreaCMP *aa = &areas[0]; - for (int i = ac - 1; i >= 0 && !stopped; i--) { - // Avoids unnecessary loop in apply_forces(). - has_wind_forces = has_wind_forces || aa[i].area->get_wind_force_magnitude() > CMP_EPSILON; - - PhysicsServer3D::AreaSpaceOverrideMode mode = aa[i].area->get_space_override_mode(); - switch (mode) { - case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE: - case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { - _compute_area_gravity(aa[i].area); - stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; - } break; - case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE: - case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { - gravity = Vector3(0, 0, 0); - _compute_area_gravity(aa[i].area); - stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE; - } break; - default: { + for (int i = ac - 1; i >= 0; i--) { + if (!gravity_done) { + PhysicsServer3D::AreaSpaceOverrideMode area_gravity_mode = (PhysicsServer3D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE); + if (area_gravity_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { + Vector3 area_gravity; + aa[i].area->compute_gravity(get_transform().get_origin(), area_gravity); + switch (area_gravity_mode) { + case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { + gravity += area_gravity; + gravity_done = area_gravity_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; + } break; + case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { + gravity = Vector3(0, 0, 0); + gravity = area_gravity; + gravity_done = area_gravity_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE; + } break; + default: { + } + } } } + + if (aa[i].area->get_wind_force_magnitude() > CMP_EPSILON) { + wind_areas.push_back(aa[i].area); + } } } + // Add default gravity and damping from space area. + if (!gravity_done) { + GodotArea3D *default_area = get_space()->get_default_area(); + ERR_FAIL_COND(!default_area); + + Vector3 default_gravity; + default_area->compute_gravity(get_transform().get_origin(), default_gravity); + gravity += default_gravity; + } + // Apply forces. add_velocity(gravity * p_delta); - if (pressure_coefficient > CMP_EPSILON || has_wind_forces) { - apply_forces(has_wind_forces); + if (pressure_coefficient > CMP_EPSILON || !wind_areas.is_empty()) { + apply_forces(wind_areas); } // Avoid soft body from 'exploding' so use some upper threshold of maximum motion @@ -1300,7 +1292,7 @@ struct _SoftBodyIntersectSegmentInfo { } }; -bool GodotSoftBodyShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotSoftBodyShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const { _SoftBodyIntersectSegmentInfo query_info; query_info.soft_body = soft_body; query_info.from = p_begin; diff --git a/servers/physics_3d/godot_soft_body_3d.h b/servers/physics_3d/godot_soft_body_3d.h index 008d5dddb8..14ddc419cf 100644 --- a/servers/physics_3d/godot_soft_body_3d.h +++ b/servers/physics_3d/godot_soft_body_3d.h @@ -101,8 +101,6 @@ class GodotSoftBody3D : public GodotCollisionObject3D { real_t drag_coefficient = 0.0; // [0,1] LocalVector<int> pinned_vertices; - Vector3 gravity; - SelfList<GodotSoftBody3D> active_list; Set<GodotConstraint3D *> constraints; @@ -113,7 +111,6 @@ class GodotSoftBody3D : public GodotCollisionObject3D { uint64_t island_step = 0; - _FORCE_INLINE_ void _compute_area_gravity(const GodotArea3D *p_area); _FORCE_INLINE_ Vector3 _compute_area_windforce(const GodotArea3D *p_area, const Face *p_face); public: @@ -151,7 +148,7 @@ public: if (index > -1) { areas.write[index].refCount -= 1; if (areas[index].refCount < 1) { - areas.remove(index); + areas.remove_at(index); } } } @@ -232,7 +229,7 @@ private: void add_velocity(const Vector3 &p_velocity); - void apply_forces(bool p_has_wind_forces); + void apply_forces(const LocalVector<GodotArea3D *> &p_wind_areas); bool create_from_trimesh(const Vector<int> &p_indices, const Vector<Vector3> &p_vertices); void generate_bending_constraints(int p_distance); @@ -257,18 +254,18 @@ class GodotSoftBodyShape3D : public GodotShape3D { public: GodotSoftBody3D *get_soft_body() const { return soft_body; } - virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_SOFT_BODY; } - virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { r_min = r_max = 0.0; } - virtual Vector3 get_support(const Vector3 &p_normal) const { return Vector3(); } - virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { r_amount = 0; } + virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_SOFT_BODY; } + virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override { r_min = r_max = 0.0; } + virtual Vector3 get_support(const Vector3 &p_normal) const override { return Vector3(); } + virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override { r_amount = 0; } - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const; - virtual bool intersect_point(const Vector3 &p_point) const; - virtual Vector3 get_closest_point_to(const Vector3 &p_point) const; - virtual Vector3 get_moment_of_inertia(real_t p_mass) const { return Vector3(); } + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override; + virtual bool intersect_point(const Vector3 &p_point) const override; + virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; + virtual Vector3 get_moment_of_inertia(real_t p_mass) const override { return Vector3(); } - virtual void set_data(const Variant &p_data) {} - virtual Variant get_data() const { return Variant(); } + virtual void set_data(const Variant &p_data) override {} + virtual Variant get_data() const override { return Variant(); } void update_bounds(); diff --git a/servers/physics_3d/godot_space_3d.cpp b/servers/physics_3d/godot_space_3d.cpp index 77b37a2353..f503273c88 100644 --- a/servers/physics_3d/godot_space_3d.cpp +++ b/servers/physics_3d/godot_space_3d.cpp @@ -148,7 +148,23 @@ bool GodotPhysicsDirectSpaceState3D::intersect_ray(const RayParameters &p_parame Vector3 shape_point, shape_normal; - if (shape->intersect_segment(local_from, local_to, shape_point, shape_normal)) { + if (shape->intersect_point(local_from)) { + if (p_parameters.hit_from_inside) { + // Hit shape at starting point. + min_d = 0; + res_point = local_from; + res_normal = Vector3(); + res_shape = shape_idx; + res_obj = col_obj; + collided = true; + break; + } else { + // Ignore shape when starting inside. + continue; + } + } + + if (shape->intersect_segment(local_from, local_to, shape_point, shape_normal, p_parameters.hit_back_faces)) { Transform3D xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); shape_point = xform.xform(shape_point); @@ -491,15 +507,17 @@ bool GodotPhysicsDirectSpaceState3D::rest_info(const ShapeParameters &p_paramete GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid); ERR_FAIL_COND_V(!shape, 0); - real_t min_contact_depth = p_parameters.margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR; - AABB aabb = p_parameters.transform.xform(shape->get_aabb()); aabb = aabb.grow(p_parameters.margin); int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); _RestCallbackData rcd; - rcd.min_allowed_depth = min_contact_depth; + + // Allowed depth can't be lower than motion length, in order to handle contacts at low speed. + real_t motion_length = p_parameters.motion.length(); + real_t min_contact_depth = p_parameters.margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR; + rcd.min_allowed_depth = MIN(motion_length, min_contact_depth); for (int i = 0; i < amount; i++) { if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { diff --git a/servers/physics_3d/godot_step_3d.cpp b/servers/physics_3d/godot_step_3d.cpp index 331d65df49..5453c4415c 100644 --- a/servers/physics_3d/godot_step_3d.cpp +++ b/servers/physics_3d/godot_step_3d.cpp @@ -220,6 +220,9 @@ void GodotStep3D::step(GodotSpace3D *p_space, real_t p_delta, int p_iterations) p_space->set_active_objects(active_count); + // Update the broadphase to register collision pairs. + p_space->update(); + { //profile profile_endtime = OS::get_singleton()->get_ticks_usec(); p_space->set_elapsed_time(GodotSpace3D::ELAPSED_TIME_INTEGRATE_FORCES, profile_endtime - profile_begtime); @@ -398,7 +401,6 @@ void GodotStep3D::step(GodotSpace3D *p_space, real_t p_delta, int p_iterations) all_constraints.clear(); - p_space->update(); p_space->unlock(); _step++; } diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index fa89ccec65..76f0b74c72 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -172,12 +172,16 @@ void PhysicsRayQueryParameters2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsRayQueryParameters2D::set_collide_with_areas); ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsRayQueryParameters2D::is_collide_with_areas_enabled); + ClassDB::bind_method(D_METHOD("set_hit_from_inside", "enable"), &PhysicsRayQueryParameters2D::set_hit_from_inside); + ClassDB::bind_method(D_METHOD("is_hit_from_inside_enabled"), &PhysicsRayQueryParameters2D::is_hit_from_inside_enabled); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "from"), "set_from", "get_from"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "to"), "set_to", "get_to"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hit_from_inside"), "set_hit_from_inside", "is_hit_from_inside_enabled"); } /////////////////////////////////////////////////////// @@ -605,9 +609,6 @@ void PhysicsServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("area_set_space", "area", "space"), &PhysicsServer2D::area_set_space); ClassDB::bind_method(D_METHOD("area_get_space", "area"), &PhysicsServer2D::area_get_space); - ClassDB::bind_method(D_METHOD("area_set_space_override_mode", "area", "mode"), &PhysicsServer2D::area_set_space_override_mode); - ClassDB::bind_method(D_METHOD("area_get_space_override_mode", "area"), &PhysicsServer2D::area_get_space_override_mode); - ClassDB::bind_method(D_METHOD("area_add_shape", "area", "shape", "transform", "disabled"), &PhysicsServer2D::area_add_shape, DEFVAL(Transform2D()), DEFVAL(false)); ClassDB::bind_method(D_METHOD("area_set_shape", "area", "shape_idx", "shape"), &PhysicsServer2D::area_set_shape); ClassDB::bind_method(D_METHOD("area_set_shape_transform", "area", "shape_idx", "transform"), &PhysicsServer2D::area_set_shape_transform); @@ -751,12 +752,15 @@ void PhysicsServer2D::_bind_methods() { BIND_ENUM_CONSTANT(SHAPE_CONCAVE_POLYGON); BIND_ENUM_CONSTANT(SHAPE_CUSTOM); + BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_OVERRIDE_MODE); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_VECTOR); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_IS_POINT); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_DISTANCE_SCALE); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_POINT_ATTENUATION); + BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE); BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP); + BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE); BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP); BIND_ENUM_CONSTANT(AREA_PARAM_PRIORITY); diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index fec03a8111..c76ec5a5b1 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -121,6 +121,8 @@ public: bool collide_with_bodies = true; bool collide_with_areas = false; + + bool hit_from_inside = false; }; struct RayResult { @@ -264,12 +266,15 @@ public: //missing attenuation? missing better override? enum AreaParameter { + AREA_PARAM_GRAVITY_OVERRIDE_MODE, AREA_PARAM_GRAVITY, AREA_PARAM_GRAVITY_VECTOR, AREA_PARAM_GRAVITY_IS_POINT, AREA_PARAM_GRAVITY_DISTANCE_SCALE, AREA_PARAM_GRAVITY_POINT_ATTENUATION, + AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE, AREA_PARAM_LINEAR_DAMP, + AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE, AREA_PARAM_ANGULAR_DAMP, AREA_PARAM_PRIORITY }; @@ -287,9 +292,6 @@ public: AREA_SPACE_OVERRIDE_REPLACE_COMBINE // Discards all previous calculations, then keeps combining }; - virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) = 0; - virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const = 0; - virtual void area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false) = 0; virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape) = 0; virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D &p_transform) = 0; @@ -604,6 +606,9 @@ public: void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; } bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; } + void set_hit_from_inside(bool p_enable) { parameters.hit_from_inside = p_enable; } + bool is_hit_from_inside_enabled() const { return parameters.hit_from_inside; } + void set_exclude(const Vector<RID> &p_exclude); Vector<RID> get_exclude() const; }; @@ -753,10 +758,9 @@ class PhysicsServer2DManager { name(p_ci.name), create_callback(p_ci.create_callback) {} - ClassInfo &operator=(const ClassInfo &p_ci) { + void operator=(const ClassInfo &p_ci) { name = p_ci.name; create_callback = p_ci.create_callback; - return *this; } }; diff --git a/servers/physics_server_2d_wrap_mt.h b/servers/physics_server_2d_wrap_mt.h index b133fa41aa..dda4eb6ffa 100644 --- a/servers/physics_server_2d_wrap_mt.h +++ b/servers/physics_server_2d_wrap_mt.h @@ -133,9 +133,6 @@ public: FUNC2(area_set_space, RID, RID); FUNC1RC(RID, area_get_space, RID); - FUNC2(area_set_space_override_mode, RID, AreaSpaceOverrideMode); - FUNC1RC(AreaSpaceOverrideMode, area_get_space_override_mode, RID); - FUNC4(area_add_shape, RID, RID, const Transform2D &, bool); FUNC3(area_set_shape, RID, int, RID); FUNC3(area_set_shape_transform, RID, int, const Transform2D &); diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index eb52cbfe5a..373f216e01 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -175,12 +175,20 @@ void PhysicsRayQueryParameters3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsRayQueryParameters3D::set_collide_with_areas); ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsRayQueryParameters3D::is_collide_with_areas_enabled); + ClassDB::bind_method(D_METHOD("set_hit_from_inside", "enable"), &PhysicsRayQueryParameters3D::set_hit_from_inside); + ClassDB::bind_method(D_METHOD("is_hit_from_inside_enabled"), &PhysicsRayQueryParameters3D::is_hit_from_inside_enabled); + + ClassDB::bind_method(D_METHOD("set_hit_back_faces", "enable"), &PhysicsRayQueryParameters3D::set_hit_back_faces); + ClassDB::bind_method(D_METHOD("is_hit_back_faces_enabled"), &PhysicsRayQueryParameters3D::is_hit_back_faces_enabled); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "from"), "set_from", "get_from"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "to"), "set_to", "get_to"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hit_from_inside"), "set_hit_from_inside", "is_hit_from_inside_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hit_back_faces"), "set_hit_back_faces", "is_hit_back_faces_enabled"); } /////////////////////////////////////////////////////// @@ -653,9 +661,6 @@ void PhysicsServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("area_set_space", "area", "space"), &PhysicsServer3D::area_set_space); ClassDB::bind_method(D_METHOD("area_get_space", "area"), &PhysicsServer3D::area_get_space); - ClassDB::bind_method(D_METHOD("area_set_space_override_mode", "area", "mode"), &PhysicsServer3D::area_set_space_override_mode); - ClassDB::bind_method(D_METHOD("area_get_space_override_mode", "area"), &PhysicsServer3D::area_get_space_override_mode); - ClassDB::bind_method(D_METHOD("area_add_shape", "area", "shape", "transform", "disabled"), &PhysicsServer3D::area_add_shape, DEFVAL(Transform3D()), DEFVAL(false)); ClassDB::bind_method(D_METHOD("area_set_shape", "area", "shape_idx", "shape"), &PhysicsServer3D::area_set_shape); ClassDB::bind_method(D_METHOD("area_set_shape_transform", "area", "shape_idx", "transform"), &PhysicsServer3D::area_set_shape_transform); @@ -901,12 +906,15 @@ void PhysicsServer3D::_bind_methods() { BIND_ENUM_CONSTANT(SHAPE_SOFT_BODY); BIND_ENUM_CONSTANT(SHAPE_CUSTOM); + BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_OVERRIDE_MODE); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_VECTOR); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_IS_POINT); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_DISTANCE_SCALE); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_POINT_ATTENUATION); + BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE); BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP); + BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE); BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP); BIND_ENUM_CONSTANT(AREA_PARAM_PRIORITY); BIND_ENUM_CONSTANT(AREA_PARAM_WIND_FORCE_MAGNITUDE); diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index b5113fd35f..bd5a3eb4b7 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -125,6 +125,9 @@ public: bool collide_with_bodies = true; bool collide_with_areas = false; + bool hit_from_inside = false; + bool hit_back_faces = true; + bool pick_ray = false; }; @@ -285,12 +288,15 @@ public: //missing attenuation? missing better override? enum AreaParameter { + AREA_PARAM_GRAVITY_OVERRIDE_MODE, AREA_PARAM_GRAVITY, AREA_PARAM_GRAVITY_VECTOR, AREA_PARAM_GRAVITY_IS_POINT, AREA_PARAM_GRAVITY_DISTANCE_SCALE, AREA_PARAM_GRAVITY_POINT_ATTENUATION, + AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE, AREA_PARAM_LINEAR_DAMP, + AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE, AREA_PARAM_ANGULAR_DAMP, AREA_PARAM_PRIORITY, AREA_PARAM_WIND_FORCE_MAGNITUDE, @@ -312,9 +318,6 @@ public: AREA_SPACE_OVERRIDE_REPLACE_COMBINE }; - virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) = 0; - virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const = 0; - virtual void area_add_shape(RID p_area, RID p_shape, const Transform3D &p_transform = Transform3D(), bool p_disabled = false) = 0; virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape) = 0; virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform3D &p_transform) = 0; @@ -805,6 +808,12 @@ public: void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; } bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; } + void set_hit_from_inside(bool p_enable) { parameters.hit_from_inside = p_enable; } + bool is_hit_from_inside_enabled() const { return parameters.hit_from_inside; } + + void set_hit_back_faces(bool p_enable) { parameters.hit_back_faces = p_enable; } + bool is_hit_back_faces_enabled() const { return parameters.hit_back_faces; } + void set_exclude(const Vector<RID> &p_exclude); Vector<RID> get_exclude() const; }; @@ -956,10 +965,9 @@ class PhysicsServer3DManager { name(p_ci.name), create_callback(p_ci.create_callback) {} - ClassInfo &operator=(const ClassInfo &p_ci) { + void operator=(const ClassInfo &p_ci) { name = p_ci.name; create_callback = p_ci.create_callback; - return *this; } }; diff --git a/servers/physics_server_3d_wrap_mt.h b/servers/physics_server_3d_wrap_mt.h index df3dc279fe..507427ecec 100644 --- a/servers/physics_server_3d_wrap_mt.h +++ b/servers/physics_server_3d_wrap_mt.h @@ -137,9 +137,6 @@ public: FUNC2(area_set_space, RID, RID); FUNC1RC(RID, area_get_space, RID); - FUNC2(area_set_space_override_mode, RID, AreaSpaceOverrideMode); - FUNC1RC(AreaSpaceOverrideMode, area_get_space_override_mode, RID); - FUNC4(area_add_shape, RID, RID, const Transform3D &, bool); FUNC3(area_set_shape, RID, int, RID); FUNC3(area_set_shape_transform, RID, int, const Transform3D &); diff --git a/servers/rendering/rasterizer_dummy.h b/servers/rendering/rasterizer_dummy.h index 44e07a1853..3451ea2d39 100644 --- a/servers/rendering/rasterizer_dummy.h +++ b/servers/rendering/rasterizer_dummy.h @@ -195,7 +195,7 @@ public: void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {} RID render_buffers_create() override { return RID(); } - void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override {} + void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override {} void gi_set_use_half_resolution(bool p_enable) override {} void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {} @@ -293,8 +293,8 @@ public: String shader_get_code(RID p_shader) const override { return ""; } void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override {} - void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) override {} - RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const override { return RID(); } + void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override {} + RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override { return RID(); } Variant shader_get_param_default(RID p_material, const StringName &p_param) const override { return Variant(); } RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); }; diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h index a2fdf95c76..bdd61123df 100644 --- a/servers/rendering/renderer_canvas_cull.h +++ b/servers/rendering/renderer_canvas_cull.h @@ -152,7 +152,7 @@ public: void erase_item(Item *p_item) { int idx = find_item(p_item); if (idx >= 0) { - child_items.remove(idx); + child_items.remove_at(idx); } } diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h index 1971c3e781..4526354d17 100644 --- a/servers/rendering/renderer_compositor.h +++ b/servers/rendering/renderer_compositor.h @@ -67,6 +67,7 @@ private: protected: static RendererCompositor *(*_create_func)(); + bool back_end = false; public: static RendererCompositor *create(); @@ -88,7 +89,7 @@ public: virtual uint64_t get_frame_number() const = 0; virtual double get_frame_delta_time() const = 0; - virtual bool is_low_end() const = 0; + _FORCE_INLINE_ virtual bool is_low_end() const { return back_end; }; virtual bool is_xr_enabled() const; RendererCompositor(); diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp index b952ecbff0..4a98cf0831 100644 --- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp +++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp @@ -460,14 +460,6 @@ void ClusterBuilderRD::bake_cluster() { RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(ClusterBuilderSharedDataRD::ClusterRender::PushConstant)); uint32_t instances = 1; -#if 0 - for (uint32_t j = i+1; j < element_count; j++) { - if (elements[i].type!=elements[j].type) { - break; - } - instances++; - } -#endif RD::get_singleton()->draw_list_draw(draw_list, true, instances); i += instances; } diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp index fdd6939a8b..cf943901d4 100644 --- a/servers/rendering/renderer_rd/effects_rd.cpp +++ b/servers/rendering/renderer_rd/effects_rd.cpp @@ -237,6 +237,43 @@ RID EffectsRD::_get_compute_uniform_set_from_image_pair(RID p_texture1, RID p_te return uniform_set; } +void EffectsRD::fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness) { + memset(&FSR_upscale.push_constant, 0, sizeof(FSRUpscalePushConstant)); + + int dispatch_x = (p_size.x + 15) / 16; + int dispatch_y = (p_size.y + 15) / 16; + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, FSR_upscale.pipeline); + + FSR_upscale.push_constant.resolution_width = p_internal_size.width; + FSR_upscale.push_constant.resolution_height = p_internal_size.height; + FSR_upscale.push_constant.upscaled_width = p_size.width; + FSR_upscale.push_constant.upscaled_height = p_size.height; + FSR_upscale.push_constant.sharpness = p_fsr_upscale_sharpness; + + //FSR Easc + FSR_upscale.push_constant.pass = FSR_UPSCALE_PASS_EASU; + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_secondary_texture), 1); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &FSR_upscale.push_constant, sizeof(FSRUpscalePushConstant)); + + RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + //FSR Rcas + FSR_upscale.push_constant.pass = FSR_UPSCALE_PASS_RCAS; + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_secondary_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_destination_texture), 1); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &FSR_upscale.push_constant, sizeof(FSRUpscalePushConstant)); + + RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1); + + RD::get_singleton()->compute_list_end(compute_list); +} + void EffectsRD::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y, bool p_panorama) { memset(©_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant)); @@ -1888,6 +1925,27 @@ void EffectsRD::sort_buffer(RID p_uniform_set, int p_size) { } EffectsRD::EffectsRD(bool p_prefer_raster_effects) { + { + Vector<String> FSR_upscale_modes; + +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) + // MoltenVK does not support some of the operations used by the normal mode of FSR. Fallback works just fine though. + FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n"); +#else + // Everyone else can use normal mode when available. + if (RD::get_singleton()->get_device_capabilities()->supports_fsr_half_float) { + FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_NORMAL\n"); + } else { + FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n"); + } +#endif + + FSR_upscale.shader.initialize(FSR_upscale_modes); + + FSR_upscale.shader_version = FSR_upscale.shader.version_create(); + FSR_upscale.pipeline = RD::get_singleton()->compute_pipeline_create(FSR_upscale.shader.version_get_shader(FSR_upscale.shader_version, 0)); + } + prefer_raster_effects = p_prefer_raster_effects; if (prefer_raster_effects) { @@ -2523,6 +2581,7 @@ EffectsRD::~EffectsRD() { RD::get_singleton()->free(index_buffer); //array gets freed as dependency RD::get_singleton()->free(filter.coefficient_buffer); + FSR_upscale.shader.version_free(FSR_upscale.shader_version); if (prefer_raster_effects) { blur_raster.shader.version_free(blur_raster.shader_version); bokeh.raster_shader.version_free(blur_raster.shader_version); diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h index 551e50ed25..6037127e82 100644 --- a/servers/rendering/renderer_rd/effects_rd.h +++ b/servers/rendering/renderer_rd/effects_rd.h @@ -45,6 +45,7 @@ #include "servers/rendering/renderer_rd/shaders/cubemap_filter_raster.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/cubemap_roughness_raster.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/fsr_upscale.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/luminance_reduce.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/resolve.glsl.gen.h" @@ -69,6 +70,28 @@ class EffectsRD { private: bool prefer_raster_effects; + enum FSRUpscalePass { + FSR_UPSCALE_PASS_EASU = 0, + FSR_UPSCALE_PASS_RCAS = 1 + }; + + struct FSRUpscalePushConstant { + float resolution_width; + float resolution_height; + float upscaled_width; + float upscaled_height; + float sharpness; + int pass; + int _unused0, _unused1; + }; + + struct FSRUpscale { + FSRUpscalePushConstant push_constant; + FsrUpscaleShaderRD shader; + RID shader_version; + RID pipeline; + } FSR_upscale; + enum BlurRasterMode { BLUR_MIPMAP, @@ -754,6 +777,7 @@ private: public: bool get_prefer_raster_effects(); + void fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness); void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID()); void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false, bool p_alpha_to_one = false); void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 0f5af96417..03ce2690bf 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -334,6 +334,14 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p const GeometryInstanceSurfaceDataCache *surf = p_params->elements[i]; const RenderElementInfo &element_info = p_params->element_info[i]; + if ((p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_SPECULAR) && !(surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) { + continue; // Objects with "Depth-prepass" transparency are included in both render lists, but should only be rendered in the transparent pass + } + + if (surf->owner->instance_count == 0) { + continue; + } + push_constant.base_index = i + p_params->element_offset; RID material_uniform_set; @@ -954,20 +962,20 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con bool uses_gi = false; float fade_alpha = 1.0; - if (p_render_list == RENDER_LIST_OPAQUE) { - if (inst->fade_near || inst->fade_far) { - float fade_dist = inst->transform.origin.distance_to(p_render_data->cam_transform.origin); - if (inst->fade_far && fade_dist > inst->fade_far_begin) { - fade_alpha = MAX(0.0, 1.0 - (fade_dist - inst->fade_far_begin) / (inst->fade_far_end - inst->fade_far_begin)); - } else if (inst->fade_near && fade_dist < inst->fade_near_end) { - fade_alpha = MAX(0.0, (fade_dist - inst->fade_near_begin) / (inst->fade_near_end - inst->fade_near_begin)); - } + if (inst->fade_near || inst->fade_far) { + float fade_dist = inst->transform.origin.distance_to(p_render_data->cam_transform.origin); + if (inst->fade_far && fade_dist > inst->fade_far_begin) { + fade_alpha = MAX(0.0, 1.0 - (fade_dist - inst->fade_far_begin) / (inst->fade_far_end - inst->fade_far_begin)); + } else if (inst->fade_near && fade_dist < inst->fade_near_end) { + fade_alpha = MAX(0.0, (fade_dist - inst->fade_near_begin) / (inst->fade_near_end - inst->fade_near_begin)); } + } - fade_alpha *= inst->force_alpha * inst->parent_fade_alpha; + fade_alpha *= inst->force_alpha * inst->parent_fade_alpha; - flags = (flags & ~INSTANCE_DATA_FLAGS_FADE_MASK) | (uint32_t(fade_alpha * 255.0) << INSTANCE_DATA_FLAGS_FADE_SHIFT); + flags = (flags & ~INSTANCE_DATA_FLAGS_FADE_MASK) | (uint32_t(fade_alpha * 255.0) << INSTANCE_DATA_FLAGS_FADE_SHIFT); + if (p_render_list == RENDER_LIST_OPAQUE) { // Setup GI if (inst->lightmap_instance.is_valid()) { int32_t lightmap_cull_index = -1; @@ -1202,6 +1210,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co scene_state.ubo.viewport_size[0] = vp_he.x; scene_state.ubo.viewport_size[1] = vp_he.y; scene_state.ubo.directional_light_count = 0; + scene_state.ubo.opaque_prepass_threshold = 0.99f; Size2i screen_size; RID opaque_framebuffer; @@ -1445,6 +1454,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_command_begin_label("Render Opaque Pass"); scene_state.ubo.directional_light_count = p_render_data->directional_light_count; + scene_state.ubo.opaque_prepass_threshold = 0.0f; _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, p_render_data->render_buffers.is_valid()); @@ -1628,6 +1638,7 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page render_data.render_info = p_render_info; scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1; + scene_state.ubo.opaque_prepass_threshold = 0.1f; _setup_environment(&render_data, true, Vector2(1, 1), !p_flip_y, Color(), false, p_use_pancake, shadow_pass_index); @@ -1714,6 +1725,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con _update_render_base_uniform_set(); scene_state.ubo.dual_paraboloid_side = 0; + scene_state.ubo.opaque_prepass_threshold = 0.0; _setup_environment(&render_data, true, Vector2(1, 1), true, Color(), false, false); @@ -1751,6 +1763,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform scene_state.ubo.dual_paraboloid_side = 0; scene_state.ubo.material_uv2_mode = false; + scene_state.ubo.opaque_prepass_threshold = 0.0f; _setup_environment(&render_data, true, Vector2(1, 1), false, Color()); @@ -1794,6 +1807,7 @@ void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p scene_state.ubo.dual_paraboloid_side = 0; scene_state.ubo.material_uv2_mode = true; + scene_state.ubo.opaque_prepass_threshold = 0.0; _setup_environment(&render_data, true, Vector2(1, 1), false, Color()); @@ -1940,7 +1954,9 @@ void RenderForwardClustered::_base_uniforms_changed() { } void RenderForwardClustered::_update_render_base_uniform_set() { - if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != storage->lightmap_array_get_version())) { + if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != storage->lightmap_array_get_version()) || base_uniform_set_updated) { + base_uniform_set_updated = false; + if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { RD::get_singleton()->free(render_base_uniform_set); } @@ -1955,18 +1971,18 @@ void RenderForwardClustered::_update_render_base_uniform_set() { u.binding = 1; u.ids.resize(12); RID *ids_ptr = u.ids.ptrw(); - ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[0] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[1] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[2] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[3] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[4] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[5] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[6] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[7] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[8] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[9] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[10] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[11] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); uniforms.push_back(u); } @@ -1985,19 +2001,19 @@ void RenderForwardClustered::_update_render_base_uniform_set() { RID sampler; switch (decals_get_filter()) { case RS::DECAL_FILTER_NEAREST: { - sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::DECAL_FILTER_NEAREST_MIPMAPS: { - sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::DECAL_FILTER_LINEAR: { - sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::DECAL_FILTER_LINEAR_MIPMAPS: { - sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: { - sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; } @@ -2012,19 +2028,19 @@ void RenderForwardClustered::_update_render_base_uniform_set() { RID sampler; switch (light_projectors_get_filter()) { case RS::LIGHT_PROJECTOR_FILTER_NEAREST: { - sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: { - sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::LIGHT_PROJECTOR_FILTER_LINEAR: { - sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS: { - sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: { - sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; } diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h index 2ba9558128..d6ab4d1db2 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -129,6 +129,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { virtual void _base_uniforms_changed() override; virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override; + bool base_uniform_set_updated = false; void _update_render_base_uniform_set(); RID _setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture); RID _setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas = false, int p_index = 0); @@ -257,7 +258,8 @@ class RenderForwardClustered : public RendererSceneRenderRD { float roughness_limiter_amount; float roughness_limiter_limit; - uint32_t roughness_limiter_pad[2]; + float opaque_prepass_threshold; + uint32_t roughness_limiter_pad; float sdf_to_bounds[16]; @@ -602,6 +604,11 @@ protected: virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override; public: + _FORCE_INLINE_ virtual void update_uniform_sets() override { + base_uniform_set_updated = true; + _update_render_base_uniform_set(); + } + virtual GeometryInstance *geometry_instance_create(RID p_base) override; virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override; virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override; diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index b74d7f9c31..768bd1de9d 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -336,11 +336,20 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { valid = true; } -void SceneShaderForwardClustered::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { +void SceneShaderForwardClustered::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { if (!p_texture.is_valid()) { - default_texture_params.erase(p_name); + if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { + default_texture_params[p_name].erase(p_index); + + if (default_texture_params[p_name].is_empty()) { + default_texture_params.erase(p_name); + } + } } else { - default_texture_params[p_name] = p_texture; + if (!default_texture_params.has(p_name)) { + default_texture_params[p_name] = Map<int, RID>(); + } + default_texture_params[p_name][p_index] = p_texture; } } @@ -576,6 +585,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin actions.renames["CUSTOM1"] = "custom1_attrib"; actions.renames["CUSTOM2"] = "custom2_attrib"; actions.renames["CUSTOM3"] = "custom3_attrib"; + actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; // not implemented but need these just in case code is in the shaders actions.renames["VIEW_INDEX"] = "0"; @@ -640,6 +650,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin actions.render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n"; actions.render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n"; actions.render_mode_defines["particle_trails"] = "#define USE_PARTICLE_TRAILS\n"; + actions.render_mode_defines["depth_draw_opaque"] = "#define USE_OPAQUE_PREPASS\n"; bool force_lambert = GLOBAL_GET("rendering/shading/overrides/force_lambert_over_burley"); diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h index b09bd7e065..f2a55939f4 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h @@ -135,7 +135,7 @@ public: uint32_t ubo_size; String code; - Map<StringName, RID> default_texture_params; + Map<StringName, Map<int, RID>> default_texture_params; DepthDraw depth_draw; DepthTest depth_test; @@ -166,7 +166,7 @@ public: uint32_t index = 0; virtual void set_code(const String &p_Code); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture); + virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const; diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index 95f5b46831..445623fb86 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -483,6 +483,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color scene_state.ubo.viewport_size[0] = vp_he.x; scene_state.ubo.viewport_size[1] = vp_he.y; scene_state.ubo.directional_light_count = 0; + scene_state.ubo.opaque_prepass_threshold = 0.0; // We can only use our full subpass approach if we're: // - not reading from SCREEN_TEXTURE/DEPTH_TEXTURE @@ -793,7 +794,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if (using_subpass_transparent) { RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer); - RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count); + RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR_TRANSPARENT, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count); render_list_params.framebuffer_format = fb_format; if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time @@ -897,6 +898,7 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr render_data.lod_distance_multiplier = p_lod_distance_multiplier; scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1; + scene_state.ubo.opaque_prepass_threshold = 0.1; _setup_environment(&render_data, true, Vector2(1, 1), !p_flip_y, Color(), false, p_use_pancake, shadow_pass_index); @@ -978,6 +980,7 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c scene_state.ubo.dual_paraboloid_side = 0; scene_state.ubo.material_uv2_mode = false; + scene_state.ubo.opaque_prepass_threshold = 0.0f; RenderDataRD render_data; render_data.cam_projection = p_cam_projection; @@ -1089,6 +1092,7 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const _update_render_base_uniform_set(); scene_state.ubo.dual_paraboloid_side = 0; + scene_state.ubo.opaque_prepass_threshold = 0.0; RenderDataRD render_data; render_data.cam_projection = p_cam_projection; @@ -1447,13 +1451,13 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const } // ADD Element - if (p_pass_mode == PASS_MODE_COLOR) { + if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) { #ifdef DEBUG_ENABLED bool force_alpha = unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW); #else bool force_alpha = false; #endif - if (!force_alpha && (surf->flags & (GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH | GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE))) { + if (!force_alpha && (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) { rl->add_element(surf); } if (force_alpha || (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA)) { @@ -1821,6 +1825,10 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr const RenderElementInfo &element_info = p_params->element_info[i]; const GeometryInstanceForwardMobile *inst = surf->owner; + if (inst->instance_count == 0) { + continue; + } + uint32_t base_spec_constants = p_params->spec_constant_base_flags; // GeometryInstanceForwardMobile::PushConstant push_constant = inst->push_constant; diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index 74bfe16557..485d08b589 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -292,7 +292,8 @@ protected: float roughness_limiter_amount; float roughness_limiter_limit; - uint32_t roughness_limiter_pad[2]; + float opaque_prepass_threshold; + uint32_t roughness_limiter_pad; // Fog uint32_t fog_enabled; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index 16d650a540..e6d9a60f94 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -325,11 +325,20 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { valid = true; } -void SceneShaderForwardMobile::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { +void SceneShaderForwardMobile::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { if (!p_texture.is_valid()) { - default_texture_params.erase(p_name); + if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { + default_texture_params[p_name].erase(p_index); + + if (default_texture_params[p_name].is_empty()) { + default_texture_params.erase(p_name); + } + } } else { - default_texture_params[p_name] = p_texture; + if (!default_texture_params.has(p_name)) { + default_texture_params[p_name] = Map<int, RID>(); + } + default_texture_params[p_name][p_index] = p_texture; } } @@ -564,6 +573,7 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p actions.renames["CUSTOM1"] = "custom1_attrib"; actions.renames["CUSTOM2"] = "custom2_attrib"; actions.renames["CUSTOM3"] = "custom3_attrib"; + actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; actions.renames["VIEW_INDEX"] = "ViewIndex"; actions.renames["VIEW_MONO_LEFT"] = "0"; @@ -627,6 +637,7 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p actions.render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n"; actions.render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n"; actions.render_mode_defines["particle_trails"] = "#define USE_PARTICLE_TRAILS\n"; + actions.render_mode_defines["depth_draw_opaque"] = "#define USE_OPAQUE_PREPASS\n"; bool force_lambert = GLOBAL_GET("rendering/shading/overrides/force_lambert_over_burley"); if (!force_lambert) { diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h index e1c10f0206..392fac1e3e 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h @@ -111,7 +111,7 @@ public: uint32_t ubo_size; String code; - Map<StringName, RID> default_texture_params; + Map<StringName, Map<int, RID>> default_texture_params; DepthDraw depth_draw; DepthTest depth_test; @@ -141,7 +141,7 @@ public: uint32_t index = 0; virtual void set_code(const String &p_Code); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture); + virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 13a3e814f6..d013099cce 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -758,6 +758,10 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend instance_count = storage->multimesh_get_instances_to_draw(multimesh); + if (instance_count == 0) { + break; + } + RID uniform_set = storage->multimesh_get_2d_uniform_set(multimesh, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET); RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, uniform_set, TRANSFORMS_UNIFORM_SET); push_constant.flags |= 1; //multimesh, trails disabled @@ -2120,11 +2124,20 @@ void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) { valid = true; } -void RendererCanvasRenderRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { +void RendererCanvasRenderRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { if (!p_texture.is_valid()) { - default_texture_params.erase(p_name); + if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { + default_texture_params[p_name].erase(p_index); + + if (default_texture_params[p_name].is_empty()) { + default_texture_params.erase(p_name); + } + } } else { - default_texture_params[p_name] = p_texture; + if (!default_texture_params.has(p_name)) { + default_texture_params[p_name] = Map<int, RID>(); + } + default_texture_params[p_name][p_index] = p_texture; } } diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index ec7d7e2854..26ccbd3bf5 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -173,14 +173,14 @@ class RendererCanvasRenderRD : public RendererCanvasRender { uint32_t ubo_size; String code; - Map<StringName, RID> default_texture_params; + Map<StringName, Map<int, RID>> default_texture_params; bool uses_screen_texture = false; bool uses_sdf = false; bool uses_time = false; virtual void set_code(const String &p_Code); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture); + virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const; diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index 559e6d5ad7..522a8e8112 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -281,12 +281,12 @@ RendererCompositorRD::RendererCompositorRD() { storage = memnew(RendererStorageRD); canvas = memnew(RendererCanvasRenderRD(storage)); - uint32_t back_end = GLOBAL_GET("rendering/vulkan/rendering/back_end"); + back_end = (bool)(int)GLOBAL_GET("rendering/vulkan/rendering/back_end"); uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE); - if (back_end == 1 || textures_per_stage < 48) { + if (back_end || textures_per_stage < 48) { scene = memnew(RendererSceneRenderImplementation::RenderForwardMobile(storage)); - } else { // back_end == 0 + } else { // back_end == false // default to our high end renderer scene = memnew(RendererSceneRenderImplementation::RenderForwardClustered(storage)); } diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h index 0230c46800..f69e40e0ff 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.h +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h @@ -116,8 +116,6 @@ public: _create_func = _create_current; } - virtual bool is_low_end() const { return false; } - static RendererCompositorRD *singleton; RendererCompositorRD(); ~RendererCompositorRD(); diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp index 807af00c8e..b6b5c90b39 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp @@ -3132,8 +3132,8 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.width = rb->width; - tf.height = rb->height; + tf.width = rb->internal_width; + tf.height = rb->internal_height; if (half_resolution) { tf.width >>= 1; tf.height >>= 1; @@ -3146,13 +3146,13 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ PushConstant push_constant; - push_constant.screen_size[0] = rb->width; - push_constant.screen_size[1] = rb->height; + push_constant.screen_size[0] = rb->internal_width; + push_constant.screen_size[1] = rb->internal_height; push_constant.z_near = p_projection.get_z_near(); push_constant.z_far = p_projection.get_z_far(); push_constant.orthogonal = p_projection.is_orthogonal(); - push_constant.proj_info[0] = -2.0f / (rb->width * p_projection.matrix[0][0]); - push_constant.proj_info[1] = -2.0f / (rb->height * p_projection.matrix[1][1]); + push_constant.proj_info[0] = -2.0f / (rb->internal_width * p_projection.matrix[0][0]); + push_constant.proj_info[1] = -2.0f / (rb->internal_height * p_projection.matrix[1][1]); push_constant.proj_info[2] = (1.0f - p_projection.matrix[0][2]) / p_projection.matrix[0][0]; push_constant.proj_info[3] = (1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1]; push_constant.max_voxel_gi_instances = MIN((uint64_t)MAX_VOXEL_GI_INSTANCES, p_voxel_gi_instances.size()); @@ -3344,9 +3344,9 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant)); if (rb->gi.using_half_size_gi) { - RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->width >> 1, rb->height >> 1, 1); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width >> 1, rb->internal_height >> 1, 1); } else { - RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->width, rb->height, 1); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width, rb->internal_height, 1); } //do barrier later to allow oeverlap //RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //no barriers, let other compute, raster and transfer happen at the same time diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 0ca2f051fa..ae8d91a73b 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -1503,8 +1503,8 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) { RD::TextureFormat tf; tf.format = _render_buffers_get_color_format(); // RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.width = rb->width; - tf.height = rb->height; + tf.width = rb->internal_width; + tf.height = rb->internal_height; tf.texture_type = rb->view_count > 1 ? RD::TEXTURE_TYPE_2D_ARRAY : RD::TEXTURE_TYPE_2D; tf.array_layers = rb->view_count; tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; @@ -1515,6 +1515,10 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) { } tf.mipmaps = mipmaps_required; + rb->sss_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + tf.width = rb->internal_width; + tf.height = rb->internal_height; rb->blur[0].texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); //the second one is smaller (only used for separatable part of blur) tf.width >>= 1; @@ -1522,8 +1526,8 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) { tf.mipmaps--; rb->blur[1].texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - int base_width = rb->width; - int base_height = rb->height; + int base_width = rb->internal_width; + int base_height = rb->internal_height; for (uint32_t i = 0; i < mipmaps_required; i++) { RenderBuffers::Blur::Mipmap mm; @@ -1577,8 +1581,8 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) { // create 4 weight textures, 2 full size, 2 half size tf.format = RD::DATA_FORMAT_R16_SFLOAT; // We could probably use DATA_FORMAT_R8_SNORM if we don't pre-multiply by blur_size but that depends on whether we can remove DEPTH_GAP - tf.width = rb->width; - tf.height = rb->height; + tf.width = rb->internal_width; + tf.height = rb->internal_height; tf.texture_type = rb->view_count > 1 ? RD::TEXTURE_TYPE_2D_ARRAY : RD::TEXTURE_TYPE_2D; tf.array_layers = rb->view_count; tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; @@ -1656,8 +1660,8 @@ void RendererSceneRenderRD::_allocate_depth_backbuffer_textures(RenderBuffers *r void RendererSceneRenderRD::_allocate_luminance_textures(RenderBuffers *rb) { ERR_FAIL_COND(!rb->luminance.current.is_null()); - int w = rb->width; - int h = rb->height; + int w = rb->internal_width; + int h = rb->internal_height; while (true) { w = MAX(w / 8, 1); @@ -1709,9 +1713,26 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) { rb->texture_fb = RID(); } - if (rb->texture.is_valid()) { - RD::get_singleton()->free(rb->texture); + if (rb->internal_texture == rb->texture && rb->internal_texture.is_valid()) { + RD::get_singleton()->free(rb->internal_texture); rb->texture = RID(); + rb->internal_texture = RID(); + rb->upscale_texture = RID(); + } else { + if (rb->texture.is_valid()) { + RD::get_singleton()->free(rb->texture); + rb->texture = RID(); + } + + if (rb->internal_texture.is_valid()) { + RD::get_singleton()->free(rb->internal_texture); + rb->internal_texture = RID(); + } + + if (rb->upscale_texture.is_valid()) { + RD::get_singleton()->free(rb->upscale_texture); + rb->upscale_texture = RID(); + } } if (rb->depth_texture.is_valid()) { @@ -1729,6 +1750,11 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) { rb->depth_back_texture = RID(); } + if (rb->sss_texture.is_valid()) { + RD::get_singleton()->free(rb->sss_texture); + rb->sss_texture = RID(); + } + for (int i = 0; i < 2; i++) { for (int m = 0; m < rb->blur[i].mipmaps.size(); m++) { // do we free the texture slice here? or is it enough to free the main texture? @@ -1818,7 +1844,7 @@ void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatri RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(!rb); - bool can_use_effects = rb->width >= 8 && rb->height >= 8; + bool can_use_effects = rb->internal_width >= 8 && rb->internal_height >= 8; if (!can_use_effects) { //just copy @@ -1829,18 +1855,18 @@ void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatri _allocate_blur_textures(rb); } - storage->get_effects()->sub_surface_scattering(rb->texture, rb->blur[0].mipmaps[0].texture, rb->depth_texture, p_camera, Size2i(rb->width, rb->height), sss_scale, sss_depth_scale, sss_quality); + storage->get_effects()->sub_surface_scattering(rb->internal_texture, rb->sss_texture, rb->depth_texture, p_camera, Size2i(rb->internal_width, rb->internal_height), sss_scale, sss_depth_scale, sss_quality); } void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive) { RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(!rb); - bool can_use_effects = rb->width >= 8 && rb->height >= 8; + bool can_use_effects = rb->internal_width >= 8 && rb->internal_height >= 8; if (!can_use_effects) { //just copy - storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->texture, RID()); + storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, RID()); return; } @@ -1852,8 +1878,8 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb if (rb->ssr.depth_scaled.is_null()) { RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R32_SFLOAT; - tf.width = rb->width / 2; - tf.height = rb->height / 2; + tf.width = rb->internal_width / 2; + tf.height = rb->internal_height / 2; tf.texture_type = RD::TEXTURE_TYPE_2D; tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT; @@ -1867,8 +1893,8 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb if (ssr_roughness_quality != RS::ENV_SSR_ROUGNESS_QUALITY_DISABLED && !rb->ssr.blur_radius[0].is_valid()) { RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = rb->width / 2; - tf.height = rb->height / 2; + tf.width = rb->internal_width / 2; + tf.height = rb->internal_height / 2; tf.texture_type = RD::TEXTURE_TYPE_2D; tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; @@ -1880,8 +1906,8 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb _allocate_blur_textures(rb); } - storage->get_effects()->screen_space_reflection(rb->texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].mipmaps[1].texture, rb->blur[1].mipmaps[0].texture, Size2i(rb->width / 2, rb->height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection); - storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->texture, rb->blur[0].mipmaps[1].texture); + storage->get_effects()->screen_space_reflection(rb->internal_texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].mipmaps[1].texture, rb->blur[1].mipmaps[0].texture, Size2i(rb->internal_width / 2, rb->internal_height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection); + storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->blur[0].mipmaps[1].texture); } void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection) { @@ -1918,15 +1944,15 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen int half_width; int half_height; if (ssao_half_size) { - buffer_width = (rb->width + 3) / 4; - buffer_height = (rb->height + 3) / 4; - half_width = (rb->width + 7) / 8; - half_height = (rb->height + 7) / 8; + buffer_width = (rb->internal_width + 3) / 4; + buffer_height = (rb->internal_height + 3) / 4; + half_width = (rb->internal_width + 7) / 8; + half_height = (rb->internal_height + 7) / 8; } else { - buffer_width = (rb->width + 1) / 2; - buffer_height = (rb->height + 1) / 2; - half_width = (rb->width + 3) / 4; - half_height = (rb->height + 3) / 4; + buffer_width = (rb->internal_width + 1) / 2; + buffer_height = (rb->internal_height + 1) / 2; + half_width = (rb->internal_width + 3) / 4; + half_height = (rb->internal_height + 3) / 4; } bool uniform_sets_are_invalid = false; if (rb->ssao.depth.is_null()) { @@ -1998,8 +2024,8 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen { RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = rb->width; - tf.height = rb->height; + tf.width = rb->internal_width; + tf.height = rb->internal_height; tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; rb->ssao.ao_final = RD::get_singleton()->texture_create(tf, RD::TextureView()); RD::get_singleton()->set_resource_name(rb->ssao.ao_final, "SSAO Final"); @@ -2022,7 +2048,7 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen settings.blur_passes = ssao_blur_passes; settings.fadeout_from = ssao_fadeout_from; settings.fadeout_to = ssao_fadeout_to; - settings.full_screen_size = Size2i(rb->width, rb->height); + settings.full_screen_size = Size2i(rb->internal_width, rb->internal_height); settings.half_screen_size = Size2i(buffer_width, buffer_height); settings.quarter_screen_size = Size2i(half_width, half_height); @@ -2086,7 +2112,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende ERR_FAIL_COND(!rb); RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_render_data->environment); - //glow (if enabled) + // Glow and override exposure (if enabled). CameraEffects *camfx = camera_effects_owner.get_or_null(p_render_data->camera_effects); bool can_use_effects = rb->width >= 8 && rb->height >= 8; @@ -2102,9 +2128,9 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende EffectsRD::BokehBuffers buffers; - // textures we use - buffers.base_texture_size = Size2i(rb->width, rb->height); - buffers.base_texture = rb->texture; + // Textures we use + buffers.base_texture_size = Size2i(rb->internal_width, rb->internal_height); + buffers.base_texture = rb->internal_texture; buffers.depth_texture = rb->depth_texture; buffers.secondary_texture = rb->blur[0].mipmaps[0].texture; buffers.half_texture[0] = rb->blur[1].mipmaps[0].texture; @@ -2114,7 +2140,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende if (can_use_storage) { storage->get_effects()->bokeh_dof(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal); } else { - // set framebuffers + // Set framebuffers. buffers.base_fb = rb->texture_fb; buffers.secondary_fb = rb->weight_buffers[1].fb; buffers.half_fb[0] = rb->weight_buffers[2].fb; @@ -2124,7 +2150,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende buffers.weight_texture[2] = rb->weight_buffers[2].weight; buffers.weight_texture[3] = rb->weight_buffers[3].weight; - // set weight buffers + // Set weight buffers. buffers.base_weight_fb = rb->base_weight_fb; storage->get_effects()->bokeh_dof_raster(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal); @@ -2143,17 +2169,17 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende double step = env->auto_exp_speed * time_step; if (can_use_storage) { - storage->get_effects()->luminance_reduction(rb->texture, Size2i(rb->width, rb->height), rb->luminance.reduce, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate); + storage->get_effects()->luminance_reduction(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate); } else { - storage->get_effects()->luminance_reduction_raster(rb->texture, Size2i(rb->width, rb->height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate); + storage->get_effects()->luminance_reduction_raster(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate); } - //swap final reduce with prev luminance + // Swap final reduce with prev luminance. SWAP(rb->luminance.current, rb->luminance.reduce.write[rb->luminance.reduce.size() - 1]); if (!can_use_storage) { SWAP(rb->luminance.current_fb, rb->luminance.fb.write[rb->luminance.fb.size() - 1]); } - RenderingServerDefault::redraw_request(); //redraw all the time if auto exposure rendering is on + RenderingServerDefault::redraw_request(); // Redraw all the time if auto exposure rendering is on. RD::get_singleton()->draw_command_end_label(); } @@ -2188,9 +2214,9 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende luminance_texture = rb->luminance.current; } if (can_use_storage) { - storage->get_effects()->gaussian_glow(rb->texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale); + storage->get_effects()->gaussian_glow(rb->internal_texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale); } else { - storage->get_effects()->gaussian_glow_raster(rb->texture, rb->blur[1].mipmaps[i].half_fb, rb->blur[1].mipmaps[i].half_texture, rb->blur[1].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale); + storage->get_effects()->gaussian_glow_raster(rb->internal_texture, rb->blur[1].mipmaps[i].half_fb, rb->blur[1].mipmaps[i].half_texture, rb->blur[1].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale); } } else { if (can_use_storage) { @@ -2207,7 +2233,6 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende { RD::get_singleton()->draw_command_begin_label("Tonemap"); - //tonemap EffectsRD::TonemapSettings tonemap; if (can_use_effects && env && env->auto_exposure && rb->luminance.current.is_valid()) { @@ -2238,7 +2263,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende } tonemap.use_debanding = rb->use_debanding; - tonemap.texture_size = Vector2i(rb->width, rb->height); + tonemap.texture_size = Vector2i(rb->internal_width, rb->internal_height); if (env) { tonemap.tonemap_mode = env->tone_mapper; @@ -2246,6 +2271,10 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.exposure = env->exposure; } + if (camfx && camfx->override_exposure_enabled) { + tonemap.exposure = camfx->override_exposure; + } + tonemap.use_color_correction = false; tonemap.use_1d_color_correction = false; tonemap.color_correction_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); @@ -2265,7 +2294,15 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier(); tonemap.view_count = p_render_data->view_count; - storage->get_effects()->tonemapper(rb->texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap); + storage->get_effects()->tonemapper(rb->internal_texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap); + + RD::get_singleton()->draw_command_end_label(); + } + + if (can_use_effects && can_use_storage && (rb->internal_width != rb->width || rb->internal_height != rb->height)) { + RD::get_singleton()->draw_command_begin_label("FSR Upscale"); + + storage->get_effects()->fsr_upscale(rb->internal_texture, rb->upscale_texture, rb->texture, Size2i(rb->internal_width, rb->internal_height), Size2i(rb->width, rb->height), rb->fsr_sharpness); RD::get_singleton()->draw_command_end_label(); } @@ -2280,6 +2317,8 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr ERR_FAIL_COND(!rb); RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_render_data->environment); + // Override exposure (if enabled). + CameraEffects *camfx = camera_effects_owner.get_or_null(p_render_data->camera_effects); bool can_use_effects = rb->width >= 8 && rb->height >= 8; @@ -2293,6 +2332,10 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr tonemap.white = env->white; } + if (camfx && camfx->override_exposure_enabled) { + tonemap.exposure = camfx->override_exposure; + } + // We don't support glow or auto exposure here, if they are needed, don't use subpasses! // The problem is that we need to use the result so far and process them before we can // apply this to our results. @@ -2619,14 +2662,28 @@ bool RendererSceneRenderRD::_render_buffers_can_be_storage() { return true; } -void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) { +void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) { ERR_FAIL_COND_MSG(p_view_count == 0, "Must have at least 1 view"); + if (!_render_buffers_can_be_storage()) { + p_internal_height = p_height; + p_internal_width = p_width; + } + + if (p_width != p_internal_width) { + float fsr_mipmap_bias = -log2f(p_width / p_internal_width) + p_fsr_mipmap_bias; + storage->sampler_rd_configure_custom(fsr_mipmap_bias); + update_uniform_sets(); + } + RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); // Should we add an overrule per viewport? + rb->internal_width = p_internal_width; + rb->internal_height = p_internal_height; rb->width = p_width; rb->height = p_height; + rb->fsr_sharpness = p_fsr_sharpness; rb->render_target = p_render_target; rb->msaa = p_msaa; rb->screen_space_aa = p_screen_space_aa; @@ -2648,8 +2705,8 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; } tf.format = _render_buffers_get_color_format(); - tf.width = rb->width; - tf.height = rb->height; + tf.width = rb->internal_width; // If set to rb->width, msaa won't crash + tf.height = rb->internal_height; // If set to rb->width, msaa won't crash tf.array_layers = rb->view_count; // create a layer for every view tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | (_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0) | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) { @@ -2657,7 +2714,17 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p } tf.usage_bits |= RD::TEXTURE_USAGE_INPUT_ATTACHMENT_BIT; // only needed when using subpasses in the mobile renderer - rb->texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + rb->internal_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + if ((p_internal_width != p_width || p_internal_height != p_height)) { + tf.width = rb->width; + tf.height = rb->height; + rb->texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + rb->upscale_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + } else { + rb->texture = rb->internal_texture; + rb->upscale_texture = rb->internal_texture; + } } { @@ -2671,8 +2738,8 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p tf.format = RD::DATA_FORMAT_R32_SFLOAT; } - tf.width = rb->width; - tf.height = rb->height; + tf.width = rb->internal_width; + tf.height = rb->internal_height; tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT; tf.array_layers = rb->view_count; // create a layer for every view @@ -2688,16 +2755,16 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p if (!_render_buffers_can_be_storage()) { // ONLY USED ON MOBILE RENDERER, ONLY USED FOR POST EFFECTS! Vector<RID> fb; - fb.push_back(rb->texture); + fb.push_back(rb->internal_texture); rb->texture_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, rb->view_count); } RID target_texture = storage->render_target_get_rd_texture(rb->render_target); - rb->data->configure(rb->texture, rb->depth_texture, target_texture, rb->width, rb->height, p_msaa, p_view_count); + rb->data->configure(rb->internal_texture, rb->depth_texture, target_texture, p_internal_width, p_internal_height, p_msaa, p_view_count); if (is_clustered_enabled()) { - rb->cluster_builder->setup(Size2i(rb->width, rb->height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->texture); + rb->cluster_builder->setup(Size2i(p_internal_width, p_internal_height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->internal_texture); } } @@ -3549,11 +3616,20 @@ void RendererSceneRenderRD::FogShaderData::set_code(const String &p_code) { valid = true; } -void RendererSceneRenderRD::FogShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { +void RendererSceneRenderRD::FogShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { if (!p_texture.is_valid()) { - default_texture_params.erase(p_name); + if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { + default_texture_params[p_name].erase(p_index); + + if (default_texture_params[p_name].is_empty()) { + default_texture_params.erase(p_name); + } + } } else { - default_texture_params[p_name] = p_texture; + if (!default_texture_params.has(p_name)) { + default_texture_params[p_name] = Map<int, RID>(); + } + default_texture_params[p_name][p_index] = p_texture; } } @@ -3778,6 +3854,18 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e rb->volumetric_fog->fog_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); RD::get_singleton()->set_resource_name(rb->volumetric_fog->fog_map, "Fog map"); +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) + Vector<uint8_t> dm; + dm.resize(target_width * target_height * volumetric_fog_depth * 4); + dm.fill(0); + + rb->volumetric_fog->density_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm); + RD::get_singleton()->set_resource_name(rb->volumetric_fog->density_map, "Fog density map"); + rb->volumetric_fog->light_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm); + RD::get_singleton()->set_resource_name(rb->volumetric_fog->light_map, "Fog light map"); + rb->volumetric_fog->emissive_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm); + RD::get_singleton()->set_resource_name(rb->volumetric_fog->emissive_map, "Fog emissive map"); +#else tf.format = RD::DATA_FORMAT_R32_UINT; tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; rb->volumetric_fog->density_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); @@ -3789,6 +3877,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e rb->volumetric_fog->emissive_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); RD::get_singleton()->set_resource_name(rb->volumetric_fog->emissive_map, "Fog emissive map"); RD::get_singleton()->texture_clear(rb->volumetric_fog->emissive_map, Color(0, 0, 0, 0), 0, 1, 0, 1); +#endif Vector<RD::Uniform> uniforms; { @@ -3854,7 +3943,11 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e { RD::Uniform u; +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +#else u.uniform_type = RD::UNIFORM_TYPE_IMAGE; +#endif u.binding = 1; u.ids.push_back(rb->volumetric_fog->emissive_map); uniforms.push_back(u); @@ -3870,7 +3963,11 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e { RD::Uniform u; +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +#else u.uniform_type = RD::UNIFORM_TYPE_IMAGE; +#endif u.binding = 3; u.ids.push_back(rb->volumetric_fog->density_map); uniforms.push_back(u); @@ -3878,7 +3975,11 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e { RD::Uniform u; +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +#else u.uniform_type = RD::UNIFORM_TYPE_IMAGE; +#endif u.binding = 4; u.ids.push_back(rb->volumetric_fog->light_map); uniforms.push_back(u); @@ -4145,14 +4246,22 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e } { RD::Uniform u; +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +#else u.uniform_type = RD::UNIFORM_TYPE_IMAGE; +#endif u.binding = 16; u.ids.push_back(rb->volumetric_fog->density_map); uniforms.push_back(u); } { RD::Uniform u; +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +#else u.uniform_type = RD::UNIFORM_TYPE_IMAGE; +#endif u.binding = 17; u.ids.push_back(rb->volumetric_fog->light_map); uniforms.push_back(u); @@ -4160,7 +4269,11 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e { RD::Uniform u; +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; +#else u.uniform_type = RD::UNIFORM_TYPE_IMAGE; +#endif u.binding = 18; u.ids.push_back(rb->volumetric_fog->emissive_map); uniforms.push_back(u); @@ -4686,9 +4799,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData if (p_render_buffers.is_valid()) { /* _debug_draw_cluster(p_render_buffers); - RENDER_TIMESTAMP("Tonemap"); - _render_buffers_post_process_and_tonemap(&render_data); */ diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index baa0144d43..98ab1a2c3c 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -456,7 +456,11 @@ private: struct RenderBuffers { RenderBufferData *data = nullptr; - int width = 0, height = 0; + int internal_width = 0; + int internal_height = 0; + int width = 0; + int height = 0; + float fsr_sharpness = 0.2f; RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED; RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED; bool use_debanding = false; @@ -466,9 +470,12 @@ private: uint64_t auto_exposure_version = 1; - RID texture; //main texture for rendering to, must be filled after done rendering + RID sss_texture; //texture for sss. This needs to be a different resolution than blur[0] + RID internal_texture; //main texture for rendering to, must be filled after done rendering + RID texture; //upscaled version of main texture (This uses the same resource as internal_texture if there is no upscaling) RID depth_texture; //main depth texture RID texture_fb; // framebuffer for the main texture, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!! + RID upscale_texture; //used when upscaling internal_texture (This uses the same resource as internal_texture if there is no upscaling) RendererSceneGIRD::SDFGI *sdfgi = nullptr; VolumetricFog *volumetric_fog = nullptr; @@ -879,12 +886,12 @@ private: String path; String code; - Map<StringName, RID> default_texture_params; + Map<StringName, Map<int, RID>> default_texture_params; bool uses_time; virtual void set_code(const String &p_Code); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture); + virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; @@ -1332,7 +1339,7 @@ public: virtual RD::DataFormat _render_buffers_get_color_format(); virtual bool _render_buffers_can_be_storage(); virtual RID render_buffers_create() override; - virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override; + virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override; virtual void gi_set_use_half_resolution(bool p_enable) override; RID render_buffers_get_depth_texture(RID p_render_buffers); @@ -1363,6 +1370,8 @@ public: float render_buffers_get_volumetric_fog_end(RID p_render_buffers); float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers); + virtual void update_uniform_sets(){}; + virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override; virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp index ce41e191e2..a9c39fb937 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp @@ -137,11 +137,20 @@ void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) { valid = true; } -void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { +void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { if (!p_texture.is_valid()) { - default_texture_params.erase(p_name); + if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { + default_texture_params[p_name].erase(p_index); + + if (default_texture_params[p_name].is_empty()) { + default_texture_params.erase(p_name); + } + } } else { - default_texture_params[p_name] = p_texture; + if (!default_texture_params.has(p_name)) { + default_texture_params[p_name] = Map<int, RID>(); + } + default_texture_params[p_name][p_index] = p_texture; } } diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h index 7f563c9bc4..8689395bea 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h @@ -118,7 +118,7 @@ private: String path; String code; - Map<StringName, RID> default_texture_params; + Map<StringName, Map<int, RID>> default_texture_params; bool uses_time; bool uses_position; @@ -127,7 +127,7 @@ private: bool uses_light; virtual void set_code(const String &p_Code); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture); + virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index 5c7fee7ec9..29e4a63cbb 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -1227,6 +1227,100 @@ RendererStorageRD::CanvasTexture::~CanvasTexture() { clear_sets(); } +void RendererStorageRD::sampler_rd_configure_custom(float p_mipmap_bias) { + for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { + for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { + RD::SamplerState sampler_state; + switch (i) { + case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: { + sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; + sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; + sampler_state.max_lod = 0; + } break; + case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: { + sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; + sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; + sampler_state.max_lod = 0; + } break; + case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: { + sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; + sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; + if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { + sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; + } else { + sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; + } + sampler_state.lod_bias = p_mipmap_bias; + } break; + case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: { + sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; + sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; + if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { + sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; + } else { + sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; + } + sampler_state.lod_bias = p_mipmap_bias; + + } break; + case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: { + sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; + sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; + if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { + sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; + } else { + sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; + } + sampler_state.lod_bias = p_mipmap_bias; + sampler_state.use_anisotropy = true; + sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level")); + } break; + case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: { + sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; + sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; + if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { + sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; + } else { + sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; + } + sampler_state.lod_bias = p_mipmap_bias; + sampler_state.use_anisotropy = true; + sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level")); + + } break; + default: { + } + } + switch (j) { + case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: { + sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; + sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; + sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; + + } break; + case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: { + sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT; + sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT; + sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT; + } break; + case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: { + sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; + sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; + sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; + } break; + default: { + } + } + + if (custom_rd_samplers[i][j].is_valid()) { + RD::get_singleton()->free(custom_rd_samplers[i][j]); + } + + custom_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state); + } + } +} + RID RendererStorageRD::canvas_texture_allocate() { return canvas_texture_owner.allocate_rid(); } @@ -1440,8 +1534,10 @@ void RendererStorageRD::shader_set_code(RID p_shader, const String &p_code) { } if (shader->data) { - for (const KeyValue<StringName, RID> &E : shader->default_texture_parameter) { - shader->data->set_default_texture_param(E.key, E.value); + for (const KeyValue<StringName, Map<int, RID>> &E : shader->default_texture_parameter) { + for (const KeyValue<int, RID> &E2 : E.value) { + shader->data->set_default_texture_param(E.key, E2.value, E2.key); + } } } } @@ -1471,17 +1567,26 @@ void RendererStorageRD::shader_get_param_list(RID p_shader, List<PropertyInfo> * } } -void RendererStorageRD::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) { +void RendererStorageRD::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) { Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND(!shader); if (p_texture.is_valid() && texture_owner.owns(p_texture)) { - shader->default_texture_parameter[p_name] = p_texture; + if (!shader->default_texture_parameter.has(p_name)) { + shader->default_texture_parameter[p_name] = Map<int, RID>(); + } + shader->default_texture_parameter[p_name][p_index] = p_texture; } else { - shader->default_texture_parameter.erase(p_name); + if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) { + shader->default_texture_parameter[p_name].erase(p_index); + + if (shader->default_texture_parameter[p_name].is_empty()) { + shader->default_texture_parameter.erase(p_name); + } + } } if (shader->data) { - shader->data->set_default_texture_param(p_name, p_texture); + shader->data->set_default_texture_param(p_name, p_texture, p_index); } for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { Material *material = E->get(); @@ -1489,11 +1594,11 @@ void RendererStorageRD::shader_set_default_texture_param(RID p_shader, const Str } } -RID RendererStorageRD::shader_get_default_texture_param(RID p_shader, const StringName &p_name) const { +RID RendererStorageRD::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const { Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND_V(!shader, RID()); - if (shader->default_texture_parameter.has(p_name)) { - return shader->default_texture_parameter[p_name]; + if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) { + return shader->default_texture_parameter[p_name][p_index]; } return RID(); @@ -2547,7 +2652,17 @@ void RendererStorageRD::MaterialData::update_uniform_buffer(const Map<StringName //regular uniform uint32_t offset = p_uniform_offsets[E.value.order]; #ifdef DEBUG_ENABLED - uint32_t size = ShaderLanguage::get_type_size(E.value.type); + uint32_t size = 0U; + // The following code enforces a 16-byte alignment of uniform arrays. + if (E.value.array_size > 0) { + size = ShaderLanguage::get_type_size(E.value.type) * E.value.array_size; + int m = (16 * E.value.array_size); + if ((size % m) != 0U) { + size += m - (size % m); + } + } else { + size = ShaderLanguage::get_type_size(E.value.type); + } ERR_CONTINUE(offset + size > p_buffer_size); #endif uint8_t *data = &p_buffer[offset]; @@ -2610,7 +2725,7 @@ RendererStorageRD::MaterialData::~MaterialData() { } } -void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, RID> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { +void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { RendererStorageRD *singleton = (RendererStorageRD *)RendererStorage::base_singleton; #ifdef TOOLS_ENABLED Texture *roughness_detect_texture = nullptr; @@ -2673,19 +2788,19 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari if (uniform_array_size > 0) { if (textures.size() < uniform_array_size) { - const Map<StringName, RID>::Element *W = p_default_textures.find(uniform_name); + const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name); for (int j = textures.size(); j < uniform_array_size; j++) { - if (W) { - textures.push_back(W->get()); + if (W && W->get().has(j)) { + textures.push_back(W->get()[j]); } else { textures.push_back(RID()); } } } } else if (textures.is_empty()) { - const Map<StringName, RID>::Element *W = p_default_textures.find(uniform_name); - if (W) { - textures.push_back(W->get()); + const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name); + if (W && W->get().has(0)) { + textures.push_back(W->get()[0]); } } } @@ -2833,7 +2948,7 @@ void RendererStorageRD::MaterialData::free_parameters_uniform_set(RID p_uniform_ } } -bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, RID> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) { +bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) { if ((uint32_t)ubo_data.size() != p_ubo_size) { p_uniform_dirty = true; if (uniform_buffer.is_valid()) { @@ -2857,7 +2972,7 @@ bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<St //check whether buffer changed if (p_uniform_dirty && ubo_data.size()) { - update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), false); + update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), true); RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), p_barrier); } @@ -5748,11 +5863,20 @@ void RendererStorageRD::ParticlesShaderData::set_code(const String &p_code) { valid = true; } -void RendererStorageRD::ParticlesShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { +void RendererStorageRD::ParticlesShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { if (!p_texture.is_valid()) { - default_texture_params.erase(p_name); + if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { + default_texture_params[p_name].erase(p_index); + + if (default_texture_params[p_name].is_empty()) { + default_texture_params.erase(p_name); + } + } } else { - default_texture_params[p_name] = p_texture; + if (!default_texture_params.has(p_name)) { + default_texture_params[p_name] = Map<int, RID>(); + } + default_texture_params[p_name][p_index] = p_texture; } } @@ -9754,6 +9878,9 @@ RendererStorageRD::RendererStorageRD() { } } + //custom sampler + sampler_rd_configure_custom(0.0f); + //default rd buffers { Vector<uint8_t> buffer; @@ -9906,7 +10033,7 @@ RendererStorageRD::RendererStorageRD() { actions.renames["RESTART"] = "restart"; actions.renames["CUSTOM"] = "PARTICLE.custom"; actions.renames["TRANSFORM"] = "PARTICLE.xform"; - actions.renames["TIME"] = "FRAME.time"; + actions.renames["TIME"] = "frame_history.data[0].time"; actions.renames["PI"] = _MKSTR(Math_PI); actions.renames["TAU"] = _MKSTR(Math_TAU); actions.renames["E"] = _MKSTR(Math_E); @@ -10084,6 +10211,15 @@ RendererStorageRD::~RendererStorageRD() { } } + //custom samplers + for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { + for (int j = 0; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { + if (custom_rd_samplers[i][j].is_valid()) { + RD::get_singleton()->free(custom_rd_samplers[i][j]); + } + } + } + //def buffers for (int i = 0; i < DEFAULT_RD_BUFFER_MAX; i++) { RD::get_singleton()->free(mesh_default_rd_buffers[i]); diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h index f13bd4a7f4..9a64480c3e 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.h +++ b/servers/rendering/renderer_rd/renderer_storage_rd.h @@ -135,7 +135,7 @@ public: struct ShaderData { virtual void set_code(const String &p_Code) = 0; - virtual void set_default_texture_param(const StringName &p_name, RID p_texture) = 0; + virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0; virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0; virtual void get_instance_param_list(List<InstanceShaderParam> *p_param_list) const = 0; @@ -152,7 +152,7 @@ public: struct MaterialData { void update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color); - void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, RID> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color); + void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color); virtual void set_render_priority(int p_priority) = 0; virtual void set_next_pass(RID p_pass) = 0; @@ -160,7 +160,7 @@ public: virtual ~MaterialData(); //to be used internally by update_parameters, in the most common configuration of material parameters - bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, RID> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL); + bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL); void free_parameters_uniform_set(RID p_uniform_set); private: @@ -320,6 +320,7 @@ private: RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX]; RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; + RID custom_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; RID default_rd_storage_buffer; /* DECAL ATLAS */ @@ -374,7 +375,7 @@ private: ShaderData *data; String code; ShaderType type; - Map<StringName, RID> default_texture_parameter; + Map<StringName, Map<int, RID>> default_texture_parameter; Set<Material *> owners; }; @@ -883,14 +884,14 @@ private: String path; String code; - Map<StringName, RID> default_texture_params; + Map<StringName, Map<int, RID>> default_texture_params; RID pipeline; bool uses_time; virtual void set_code(const String &p_Code); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture); + virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const; virtual bool is_param_texture(const StringName &p_param) const; @@ -1391,6 +1392,13 @@ public: _FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) { return default_rd_samplers[p_filter][p_repeat]; } + _FORCE_INLINE_ RID sampler_rd_get_custom(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) { + return custom_rd_samplers[p_filter][p_repeat]; + } + + void sampler_rd_configure_custom(float mipmap_bias); + + void sampler_rd_set_default(float p_mipmap_bias); /* CANVAS TEXTURE API */ @@ -1414,8 +1422,8 @@ public: String shader_get_code(RID p_shader) const; void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const; - void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture); - RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const; + void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index); + RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const; Variant shader_get_param_default(RID p_shader, const StringName &p_param) const; void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function); diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.cpp b/servers/rendering/renderer_rd/shader_compiler_rd.cpp index 215959bb6a..b02b3d2723 100644 --- a/servers/rendering/renderer_rd/shader_compiler_rd.cpp +++ b/servers/rendering/renderer_rd/shader_compiler_rd.cpp @@ -227,6 +227,13 @@ static String _prestr(SL::DataPrecision p_pres, bool p_force_highp = false) { return ""; } +static String _constr(bool p_is_const) { + if (p_is_const) { + return "const "; + } + return ""; +} + static String _qualstr(SL::ArgumentQualifier p_qual) { switch (p_qual) { case SL::ARGUMENT_QUALIFIER_IN: @@ -417,9 +424,7 @@ void ShaderCompilerRD::_dump_function_deps(const SL::ShaderNode *p_node, const S if (i > 0) { header += ", "; } - if (fnode->arguments[i].is_const) { - header += "const "; - } + header += _constr(fnode->arguments[i].is_const); if (fnode->arguments[i].type == SL::TYPE_STRUCT) { header += _qualstr(fnode->arguments[i].qualifier) + _mkid(fnode->arguments[i].type_str) + " " + _mkid(fnode->arguments[i].name); } else { @@ -656,6 +661,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge uniform_sizes.write[uniform.order] = _get_datatype_size(ShaderLanguage::TYPE_UINT); uniform_alignments.write[uniform.order] = _get_datatype_alignment(ShaderLanguage::TYPE_UINT); } else { + // The following code enforces a 16-byte alignment of uniform arrays. if (uniform.array_size > 0) { int size = _get_datatype_size(uniform.type) * uniform.array_size; int m = (16 * uniform.array_size); @@ -663,10 +669,11 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge size += m - (size % m); } uniform_sizes.write[uniform.order] = size; + uniform_alignments.write[uniform.order] = 16; } else { uniform_sizes.write[uniform.order] = _get_datatype_size(uniform.type); + uniform_alignments.write[uniform.order] = _get_datatype_alignment(uniform.type); } - uniform_alignments.write[uniform.order] = _get_datatype_alignment(uniform.type); } } @@ -791,7 +798,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge for (int i = 0; i < pnode->vconstants.size(); i++) { const SL::ShaderNode::Constant &cnode = pnode->vconstants[i]; String gcode; - gcode += "const "; + gcode += _constr(true); gcode += _prestr(cnode.precision, ShaderLanguage::is_float_type(cnode.type)); if (cnode.type == SL::TYPE_STRUCT) { gcode += _mkid(cnode.type_str); @@ -875,9 +882,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge SL::VariableDeclarationNode *vdnode = (SL::VariableDeclarationNode *)p_node; String declaration; - if (vdnode->is_const) { - declaration += "const "; - } + declaration += _constr(vdnode->is_const); if (vdnode->datatype == SL::TYPE_STRUCT) { declaration += _mkid(vdnode->struct_name); } else { @@ -997,9 +1002,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge case SL::Node::TYPE_ARRAY_DECLARATION: { SL::ArrayDeclarationNode *adnode = (SL::ArrayDeclarationNode *)p_node; String declaration; - if (adnode->is_const) { - declaration += "const "; - } + declaration += _constr(adnode->is_const); if (adnode->datatype == SL::TYPE_STRUCT) { declaration += _mkid(adnode->struct_name); } else { @@ -1315,6 +1318,9 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge code += ")"; } break; + case SL::OP_EMPTY: { + // Semicolon (or empty statement) - ignored. + } break; default: { if (p_use_scope) { diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp index b9a8947fa2..2568090918 100644 --- a/servers/rendering/renderer_rd/shader_rd.cpp +++ b/servers/rendering/renderer_rd/shader_rd.cpp @@ -177,6 +177,9 @@ void ShaderRD::_build_variant_code(StringBuilder &builder, uint32_t p_variant, c for (const KeyValue<StringName, CharString> &E : p_version->code_sections) { builder.append(String("#define ") + String(E.key) + "_CODE_USED\n"); } +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) + builder.append("#define MOLTENVK_USED\n"); +#endif } break; case StageTemplate::Chunk::TYPE_MATERIAL_UNIFORMS: { builder.append(p_version->uniforms.get_data()); //uniforms (same for vertex and fragment) diff --git a/servers/rendering/renderer_rd/shaders/fsr_upscale.glsl b/servers/rendering/renderer_rd/shaders/fsr_upscale.glsl new file mode 100644 index 0000000000..4e2ba84033 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/fsr_upscale.glsl @@ -0,0 +1,173 @@ +/*************************************************************************/ +/* fsr_upscale.glsl */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#[compute] + +#version 450 + +#VERSION_DEFINES + +#define A_GPU +#define A_GLSL + +#ifdef MODE_FSR_UPSCALE_NORMAL + +#define A_HALF + +#endif + +#include "thirdparty/amd-fsr/ffx_a.h" + +layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; + +layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly image2D fsr_image; +layout(set = 0, binding = 0) uniform sampler2D source_image; + +#define FSR_UPSCALE_PASS_TYPE_EASU 0 +#define FSR_UPSCALE_PASS_TYPE_RCAS 1 + +layout(push_constant, binding = 1, std430) uniform Params { + float resolution_width; + float resolution_height; + float upscaled_width; + float upscaled_height; + float sharpness; + int pass; +} +params; + +AU4 Const0, Const1, Const2, Const3; + +#ifdef MODE_FSR_UPSCALE_FALLBACK + +#define FSR_EASU_F +AF4 FsrEasuRF(AF2 p) { + AF4 res = textureGather(source_image, p, 0); + return res; +} +AF4 FsrEasuGF(AF2 p) { + AF4 res = textureGather(source_image, p, 1); + return res; +} +AF4 FsrEasuBF(AF2 p) { + AF4 res = textureGather(source_image, p, 2); + return res; +} + +#define FSR_RCAS_F +AF4 FsrRcasLoadF(ASU2 p) { + return AF4(texelFetch(source_image, ASU2(p), 0)); +} +void FsrRcasInputF(inout AF1 r, inout AF1 g, inout AF1 b) {} + +#else + +#define FSR_EASU_H +AH4 FsrEasuRH(AF2 p) { + AH4 res = AH4(textureGather(source_image, p, 0)); + return res; +} +AH4 FsrEasuGH(AF2 p) { + AH4 res = AH4(textureGather(source_image, p, 1)); + return res; +} +AH4 FsrEasuBH(AF2 p) { + AH4 res = AH4(textureGather(source_image, p, 2)); + return res; +} + +#define FSR_RCAS_H +AH4 FsrRcasLoadH(ASW2 p) { + return AH4(texelFetch(source_image, ASU2(p), 0)); +} +void FsrRcasInputH(inout AH1 r, inout AH1 g, inout AH1 b) {} + +#endif + +#include "thirdparty/amd-fsr/ffx_fsr1.h" + +void fsr_easu_pass(AU2 pos) { +#ifdef MODE_FSR_UPSCALE_NORMAL + + AH3 Gamma2Color = AH3(0, 0, 0); + FsrEasuH(Gamma2Color, pos, Const0, Const1, Const2, Const3); + imageStore(fsr_image, ASU2(pos), AH4(Gamma2Color, 1)); + +#else + + AF3 Gamma2Color = AF3(0, 0, 0); + FsrEasuF(Gamma2Color, pos, Const0, Const1, Const2, Const3); + imageStore(fsr_image, ASU2(pos), AF4(Gamma2Color, 1)); + +#endif +} + +void fsr_rcas_pass(AU2 pos) { +#ifdef MODE_FSR_UPSCALE_NORMAL + + AH3 Gamma2Color = AH3(0, 0, 0); + FsrRcasH(Gamma2Color.r, Gamma2Color.g, Gamma2Color.b, pos, Const0); + imageStore(fsr_image, ASU2(pos), AH4(Gamma2Color, 1)); + +#else + + AF3 Gamma2Color = AF3(0, 0, 0); + FsrRcasF(Gamma2Color.r, Gamma2Color.g, Gamma2Color.b, pos, Const0); + imageStore(fsr_image, ASU2(pos), AF4(Gamma2Color, 1)); + +#endif +} + +void fsr_pass(AU2 pos) { + if (params.pass == FSR_UPSCALE_PASS_TYPE_EASU) { + fsr_easu_pass(pos); + } else if (params.pass == FSR_UPSCALE_PASS_TYPE_RCAS) { + fsr_rcas_pass(pos); + } +} + +void main() { + // Clang does not like unused functions. If ffx_a.h is included in the binary, clang will throw a fit and not compile so we must configure FSR in this shader + if (params.pass == FSR_UPSCALE_PASS_TYPE_EASU) { + FsrEasuCon(Const0, Const1, Const2, Const3, params.resolution_width, params.resolution_height, params.resolution_width, params.resolution_height, params.upscaled_width, params.upscaled_height); + } else if (params.pass == FSR_UPSCALE_PASS_TYPE_RCAS) { + FsrRcasCon(Const0, params.sharpness); + } + + AU2 gxy = ARmp8x8(gl_LocalInvocationID.x) + AU2(gl_WorkGroupID.x << 4u, gl_WorkGroupID.y << 4u); + + fsr_pass(gxy); + gxy.x += 8u; + fsr_pass(gxy); + gxy.y += 8u; + fsr_pass(gxy); + gxy.x -= 8u; + fsr_pass(gxy); +} diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl index 4119e98d15..e4628b2d5a 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl @@ -6,6 +6,8 @@ #include "scene_forward_clustered_inc.glsl" +#define SHADER_IS_SRGB false + /* INPUT ATTRIBS */ layout(location = 0) in vec3 vertex_attrib; @@ -358,6 +360,8 @@ void main() { #VERSION_DEFINES +#define SHADER_IS_SRGB false + /* Specialization Constants (Toggles) */ layout(constant_id = 0) const bool sc_use_forward_gi = false; @@ -691,7 +695,7 @@ void main() { #endif // ALPHA_ANTIALIASING_EDGE_USED #ifdef USE_OPAQUE_PREPASS - if (alpha < opaque_prepass_threshold) { + if (alpha < scene_data.opaque_prepass_threshold) { discard; } #endif // USE_OPAQUE_PREPASS @@ -1529,7 +1533,7 @@ void main() { float size_A = sc_use_light_soft_shadows ? directional_lights.data[i].size : 0.0; - light_compute(normal, directional_lights.data[i].direction, normalize(view), size_A, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0, + light_compute(normal, directional_lights.data[i].direction, normalize(view), size_A, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0, albedo, alpha, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -1540,7 +1544,7 @@ void main() { transmittance_z, #endif #ifdef LIGHT_RIM_USED - rim, rim_tint, albedo, + rim, rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED clearcoat, clearcoat_gloss, @@ -1548,9 +1552,6 @@ void main() { #ifdef LIGHT_ANISOTROPY_USED binormal, tangent, anisotropy, #endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif diffuse_light, specular_light); } @@ -1603,7 +1604,7 @@ void main() { shadow = blur_shadow(shadow); - light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, + light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -1615,7 +1616,6 @@ void main() { #ifdef LIGHT_RIM_USED rim, rim_tint, - albedo, #endif #ifdef LIGHT_CLEARCOAT_USED clearcoat, clearcoat_gloss, @@ -1623,9 +1623,6 @@ void main() { #ifdef LIGHT_ANISOTROPY_USED tangent, binormal, anisotropy, #endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif diffuse_light, specular_light); } } @@ -1679,7 +1676,7 @@ void main() { shadow = blur_shadow(shadow); - light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, + light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -1691,7 +1688,6 @@ void main() { #ifdef LIGHT_RIM_USED rim, rim_tint, - albedo, #endif #ifdef LIGHT_CLEARCOAT_USED clearcoat, clearcoat_gloss, @@ -1699,9 +1695,6 @@ void main() { #ifdef LIGHT_ANISOTROPY_USED tangent, binormal, anisotropy, #endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif diffuse_light, specular_light); } } @@ -1718,7 +1711,7 @@ void main() { #ifdef USE_OPAQUE_PREPASS - if (alpha < opaque_prepass_threshold) { + if (alpha < scene_data.opaque_prepass_threshold) { discard; } @@ -1764,7 +1757,11 @@ void main() { } } +#ifdef MOLTENVK_USED + imageStore(geom_facing_grid, grid_pos, uvec4(imageLoad(geom_facing_grid, grid_pos).r | facing_bits)); //store facing bits +#else imageAtomicOr(geom_facing_grid, grid_pos, facing_bits); //store facing bits +#endif if (length(emission) > 0.001) { float lumas[6]; diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl index c8489f2137..be29cf4f58 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl @@ -208,7 +208,8 @@ layout(set = 1, binding = 0, std140) uniform SceneData { float roughness_limiter_amount; float roughness_limiter_limit; - uvec2 roughness_limiter_pad; + float opaque_prepass_threshold; + uint roughness_limiter_pad; mat4 sdf_to_bounds; diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl index b26489ddf1..d22f936a35 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl @@ -73,7 +73,7 @@ vec3 F0(float metallic, float specular, vec3 albedo) { return mix(vec3(dielectric), albedo, vec3(metallic)); } -void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float attenuation, vec3 f0, uint orms, float specular_amount, +void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float attenuation, vec3 f0, uint orms, float specular_amount, vec3 albedo, inout float alpha, #ifdef LIGHT_BACKLIGHT_USED vec3 backlight, #endif @@ -84,7 +84,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte float transmittance_z, #endif #ifdef LIGHT_RIM_USED - float rim, float rim_tint, vec3 rim_color, + float rim, float rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED float clearcoat, float clearcoat_gloss, @@ -92,9 +92,6 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte #ifdef LIGHT_ANISOTROPY_USED vec3 B, vec3 T, float anisotropy, #endif -#ifdef USE_SHADOW_TO_OPACITY - inout float alpha, -#endif inout vec3 diffuse_light, inout vec3 specular_light) { vec4 orms_unpacked = unpackUnorm4x8(orms); @@ -171,7 +168,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte #if defined(LIGHT_RIM_USED) float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0)); - diffuse_light += rim_light * rim * mix(vec3(1.0), rim_color, rim_tint) * light_color; + diffuse_light += rim_light * rim * mix(vec3(1.0), albedo, rim_tint) * light_color; #endif #ifdef LIGHT_TRANSMITTANCE_USED @@ -577,7 +574,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { return 1.0; } -void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow, +void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow, vec3 albedo, inout float alpha, #ifdef LIGHT_BACKLIGHT_USED vec3 backlight, #endif @@ -587,7 +584,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v float transmittance_boost, #endif #ifdef LIGHT_RIM_USED - float rim, float rim_tint, vec3 rim_color, + float rim, float rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED float clearcoat, float clearcoat_gloss, @@ -595,9 +592,6 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v #ifdef LIGHT_ANISOTROPY_USED vec3 binormal, vec3 tangent, float anisotropy, #endif -#ifdef USE_SHADOW_TO_OPACITY - inout float alpha, -#endif inout vec3 diffuse_light, inout vec3 specular_light) { vec3 light_rel_vec = omni_lights.data[idx].position - vertex; float light_length = length(light_rel_vec); @@ -703,7 +697,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v light_attenuation *= shadow; - light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, omni_lights.data[idx].specular_amount, + light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, omni_lights.data[idx].specular_amount, albedo, alpha, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -714,7 +708,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v transmittance_z, #endif #ifdef LIGHT_RIM_USED - rim * omni_attenuation, rim_tint, rim_color, + rim * omni_attenuation, rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED clearcoat, clearcoat_gloss, @@ -722,9 +716,6 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v #ifdef LIGHT_ANISOTROPY_USED binormal, tangent, anisotropy, #endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif diffuse_light, specular_light); } @@ -823,7 +814,7 @@ vec2 normal_to_panorama(vec3 n) { return panorama_coords; } -void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow, +void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow, vec3 albedo, inout float alpha, #ifdef LIGHT_BACKLIGHT_USED vec3 backlight, #endif @@ -833,7 +824,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v float transmittance_boost, #endif #ifdef LIGHT_RIM_USED - float rim, float rim_tint, vec3 rim_color, + float rim, float rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED float clearcoat, float clearcoat_gloss, @@ -841,9 +832,6 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v #ifdef LIGHT_ANISOTROPY_USED vec3 binormal, vec3 tangent, float anisotropy, #endif -#ifdef USE_SHADOW_TO_OPACITY - inout float alpha, -#endif inout vec3 diffuse_light, inout vec3 specular_light) { vec3 light_rel_vec = spot_lights.data[idx].position - vertex; @@ -910,7 +898,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v } light_attenuation *= shadow; - light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, spot_lights.data[idx].specular_amount, + light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, spot_lights.data[idx].specular_amount, albedo, alpha, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -921,7 +909,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v transmittance_z, #endif #ifdef LIGHT_RIM_USED - rim * spot_attenuation, rim_tint, rim_color, + rim * spot_attenuation, rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED clearcoat, clearcoat_gloss, @@ -929,9 +917,6 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v #ifdef LIGHT_ANISOTROPY_USED binormal, tangent, anisotropy, #endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif diffuse_light, specular_light); } diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl index 2f5cc58619..e92fbecfd0 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl @@ -7,6 +7,8 @@ /* Include our forward mobile UBOs definitions etc. */ #include "scene_forward_mobile_inc.glsl" +#define SHADER_IS_SRGB false + /* INPUT ATTRIBS */ layout(location = 0) in vec3 vertex_attrib; @@ -370,6 +372,8 @@ void main() { #VERSION_DEFINES +#define SHADER_IS_SRGB false + /* Specialization Constants */ #if !defined(MODE_RENDER_DEPTH) @@ -701,7 +705,7 @@ void main() { #endif // ALPHA_ANTIALIASING_EDGE_USED #ifdef USE_OPAQUE_PREPASS - if (alpha < opaque_prepass_threshold) { + if (alpha < scene_data.opaque_prepass_threshold) { discard; } #endif // USE_OPAQUE_PREPASS @@ -1345,7 +1349,7 @@ void main() { #endif blur_shadow(shadow); - light_compute(normal, directional_lights.data[i].direction, normalize(view), 0.0, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0, + light_compute(normal, directional_lights.data[i].direction, normalize(view), 0.0, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0, albedo, alpha, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -1358,7 +1362,7 @@ void main() { #endif */ #ifdef LIGHT_RIM_USED - rim, rim_tint, albedo, + rim, rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED clearcoat, clearcoat_gloss, @@ -1369,9 +1373,6 @@ void main() { #ifdef USE_SOFT_SHADOW directional_lights.data[i].size, #endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif diffuse_light, specular_light); } @@ -1395,7 +1396,7 @@ void main() { shadow = blur_shadow(shadow); - light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, + light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -1409,7 +1410,6 @@ void main() { #ifdef LIGHT_RIM_USED rim, rim_tint, - albedo, #endif #ifdef LIGHT_CLEARCOAT_USED clearcoat, clearcoat_gloss, @@ -1417,9 +1417,6 @@ void main() { #ifdef LIGHT_ANISOTROPY_USED tangent, binormal, anisotropy, #endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif diffuse_light, specular_light); } } //omni lights @@ -1443,7 +1440,7 @@ void main() { shadow = blur_shadow(shadow); - light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, + light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha, #ifdef LIGHT_BACKLIGHT_USED backlight, #endif @@ -1457,7 +1454,6 @@ void main() { #ifdef LIGHT_RIM_USED rim, rim_tint, - albedo, #endif #ifdef LIGHT_CLEARCOAT_USED clearcoat, clearcoat_gloss, @@ -1465,9 +1461,6 @@ void main() { #ifdef LIGHT_ANISOTROPY_USED tangent, binormal, anisotropy, #endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif diffuse_light, specular_light); } } //spot lights @@ -1483,7 +1476,7 @@ void main() { #ifdef USE_OPAQUE_PREPASS - if (alpha < opaque_prepass_threshold) { + if (alpha < scene_data.opaque_prepass_threshold) { discard; } diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl index eb8fb49598..a9a4fce82a 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl @@ -168,7 +168,8 @@ layout(set = 1, binding = 0, std140) uniform SceneData { mediump float roughness_limiter_amount; mediump float roughness_limiter_limit; - uvec2 roughness_limiter_pad; + mediump float opaque_prepass_threshold; + uint roughness_limiter_pad; bool fog_enabled; highp float fog_density; diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl index afc5d68776..181d3b272f 100644 --- a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl +++ b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl @@ -47,7 +47,13 @@ layout(push_constant, binding = 0, std430) uniform Params { } params; +#ifdef MOLTENVK_USED +layout(set = 1, binding = 1) volatile buffer emissive_only_map_buffer { + uint emissive_only_map[]; +}; +#else layout(r32ui, set = 1, binding = 1) uniform volatile uimage3D emissive_only_map; +#endif layout(set = 1, binding = 2, std140) uniform SceneParams { vec2 fog_frustum_size_begin; @@ -71,8 +77,17 @@ layout(set = 1, binding = 2, std140) uniform SceneParams { } scene_params; +#ifdef MOLTENVK_USED +layout(set = 1, binding = 3) volatile buffer density_only_map_buffer { + uint density_only_map[]; +}; +layout(set = 1, binding = 4) volatile buffer light_only_map_buffer { + uint light_only_map[]; +}; +#else layout(r32ui, set = 1, binding = 3) uniform volatile uimage3D density_only_map; layout(r32ui, set = 1, binding = 4) uniform volatile uimage3D light_only_map; +#endif #ifdef MATERIAL_UNIFORMS_USED layout(set = 2, binding = 0, std140) uniform MaterialUniforms{ @@ -115,6 +130,9 @@ void main() { if (any(greaterThanEqual(pos, scene_params.fog_volume_size))) { return; //do not compute } +#ifdef MOLTENVK_USED + uint lpos = pos.z * scene_params.fog_volume_size.x * scene_params.fog_volume_size.y + pos.y * scene_params.fog_volume_size.x + pos.x; +#endif vec3 posf = vec3(pos); @@ -197,7 +215,11 @@ void main() { density *= cull_mask; if (abs(density) > 0.001) { int final_density = int(density * DENSITY_SCALE); +#ifdef MOLTENVK_USED + atomicAdd(density_only_map[lpos], uint(final_density)); +#else imageAtomicAdd(density_only_map, pos, uint(final_density)); +#endif #ifdef EMISSION_USED { @@ -207,7 +229,11 @@ void main() { uvec3 emission_u = uvec3(emission.r * 511.0, emission.g * 511.0, emission.b * 255.0); // R and G have 11 bits each and B has 10. Then pack them into a 32 bit uint uint final_emission = emission_u.r << 21 | emission_u.g << 10 | emission_u.b; +#ifdef MOLTENVK_USED + uint prev_emission = atomicAdd(emissive_only_map[lpos], final_emission); +#else uint prev_emission = imageAtomicAdd(emissive_only_map, pos, final_emission); +#endif // Adding can lead to colors overflowing, so validate uvec3 prev_emission_u = uvec3(prev_emission >> 21, (prev_emission << 11) >> 21, prev_emission % 1024); @@ -219,7 +245,11 @@ void main() { if (any(overflowing)) { uvec3 overflow_factor = mix(uvec3(0), uvec3(2047 << 21, 2047 << 10, 1023), overflowing); uint force_max = overflow_factor.r | overflow_factor.g | overflow_factor.b; +#ifdef MOLTENVK_USED + atomicOr(emissive_only_map[lpos], force_max); +#else imageAtomicOr(emissive_only_map, pos, force_max); +#endif } } #endif @@ -230,7 +260,11 @@ void main() { uvec3 scattering_u = uvec3(scattering.r * 2047.0, scattering.g * 2047.0, scattering.b * 1023.0); // R and G have 11 bits each and B has 10. Then pack them into a 32 bit uint uint final_scattering = scattering_u.r << 21 | scattering_u.g << 10 | scattering_u.b; +#ifdef MOLTENVK_USED + uint prev_scattering = atomicAdd(light_only_map[lpos], final_scattering); +#else uint prev_scattering = imageAtomicAdd(light_only_map, pos, final_scattering); +#endif // Adding can lead to colors overflowing, so validate uvec3 prev_scattering_u = uvec3(prev_scattering >> 21, (prev_scattering << 11) >> 21, prev_scattering % 1024); @@ -242,7 +276,11 @@ void main() { if (any(overflowing)) { uvec3 overflow_factor = mix(uvec3(0), uvec3(2047 << 21, 2047 << 10, 1023), overflowing); uint force_max = overflow_factor.r | overflow_factor.g | overflow_factor.b; +#ifdef MOLTENVK_USED + atomicOr(light_only_map[lpos], force_max); +#else imageAtomicOr(light_only_map, pos, force_max); +#endif } } #endif // ALBEDO_USED diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl b/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl index 3d6fbb5653..747f88960c 100644 --- a/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl +++ b/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl @@ -190,9 +190,22 @@ params; #ifndef MODE_COPY layout(set = 0, binding = 15) uniform texture3D prev_density_texture; +#ifdef MOLTENVK_USED +layout(set = 0, binding = 16) buffer density_only_map_buffer { + uint density_only_map[]; +}; +layout(set = 0, binding = 17) buffer light_only_map_buffer { + uint light_only_map[]; +}; +layout(set = 0, binding = 18) buffer emissive_only_map_buffer { + uint emissive_only_map[]; +}; +#else layout(r32ui, set = 0, binding = 16) uniform uimage3D density_only_map; layout(r32ui, set = 0, binding = 17) uniform uimage3D light_only_map; layout(r32ui, set = 0, binding = 18) uniform uimage3D emissive_only_map; +#endif + #ifdef USE_RADIANCE_CUBEMAP_ARRAY layout(set = 0, binding = 19) uniform textureCubeArray sky_texture; #else @@ -272,6 +285,9 @@ void main() { if (any(greaterThanEqual(pos, params.fog_volume_size))) { return; //do not compute } +#ifdef MOLTENVK_USED + uint lpos = pos.z * params.fog_volume_size.x * params.fog_volume_size.y + pos.y * params.fog_volume_size.x + pos.x; +#endif vec3 posf = vec3(pos); @@ -335,15 +351,28 @@ void main() { vec3 total_light = vec3(0.0); float total_density = params.base_density; +#ifdef MOLTENVK_USED + uint local_density = density_only_map[lpos]; +#else uint local_density = imageLoad(density_only_map, pos).x; +#endif + total_density += float(int(local_density)) / DENSITY_SCALE; total_density = max(0.0, total_density); +#ifdef MOLTENVK_USED + uint scattering_u = light_only_map[lpos]; +#else uint scattering_u = imageLoad(light_only_map, pos).x; +#endif vec3 scattering = vec3(scattering_u >> 21, (scattering_u << 11) >> 21, scattering_u % 1024) / vec3(2047.0, 2047.0, 1023.0); scattering += params.base_scattering * params.base_density; +#ifdef MOLTENVK_USED + uint emission_u = emissive_only_map[lpos]; +#else uint emission_u = imageLoad(emissive_only_map, pos).x; +#endif vec3 emission = vec3(emission_u >> 21, (emission_u << 11) >> 21, emission_u % 1024) / vec3(511.0, 511.0, 255.0); emission += params.base_emission * params.base_density; @@ -673,10 +702,16 @@ void main() { final_density = mix(final_density, reprojected_density, reproject_amount); imageStore(density_map, pos, final_density); +#ifdef MOLTENVK_USED + density_only_map[lpos] = 0; + light_only_map[lpos] = 0; + emissive_only_map[lpos] = 0; +#else imageStore(density_only_map, pos, uvec4(0)); imageStore(light_only_map, pos, uvec4(0)); imageStore(emissive_only_map, pos, uvec4(0)); #endif +#endif #ifdef MODE_FOG diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h index b6e99e4be5..02c845581c 100644 --- a/servers/rendering/renderer_scene.h +++ b/servers/rendering/renderer_scene.h @@ -191,7 +191,7 @@ public: virtual RID render_buffers_create() = 0; - virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) = 0; + virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) = 0; virtual void gi_set_use_half_resolution(bool p_enable) = 0; diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index e338e526a0..5b834db178 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -644,6 +644,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { scene_render->geometry_instance_set_use_dynamic_gi(geom->geometry_instance, instance->dynamic_gi); scene_render->geometry_instance_set_cast_double_sided_shadows(geom->geometry_instance, instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED); scene_render->geometry_instance_set_use_lightmap(geom->geometry_instance, RID(), instance->lightmap_uv_scale, instance->lightmap_slice_index); + scene_render->geometry_instance_set_transparency(geom->geometry_instance, instance->transparency); if (instance->lightmap_sh.size() == 9) { scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, instance->lightmap_sh.ptr()); } @@ -839,6 +840,8 @@ void RendererSceneCull::instance_geometry_set_transparency(RID p_instance, float Instance *instance = instance_owner.get_or_null(p_instance); ERR_FAIL_COND(!instance); + instance->transparency = p_transparency; + if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) { InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); scene_render->geometry_instance_set_transparency(geom->geometry_instance, p_transparency); @@ -1310,7 +1313,7 @@ void RendererSceneCull::_update_instance_visibility_dependencies(Instance *p_ins bool needs_visibility_cull = has_visibility_range && is_geometry_instance && p_instance->array_index != -1; if (!needs_visibility_cull && p_instance->visibility_index != -1) { - p_instance->scenario->instance_visibility.remove(p_instance->visibility_index); + p_instance->scenario->instance_visibility.remove_at(p_instance->visibility_index); p_instance->visibility_index = -1; } else if (needs_visibility_cull && p_instance->visibility_index == -1) { InstanceVisibilityData vd; diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h index de22bc1328..e51a1fc02e 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -439,17 +439,18 @@ public: RID self; //scenario stuff DynamicBVH::ID indexer_id; - int32_t array_index; + int32_t array_index = -1; int32_t visibility_index = -1; - float visibility_range_begin; - float visibility_range_end; - float visibility_range_begin_margin; - float visibility_range_end_margin; + float visibility_range_begin = 0.0f; + float visibility_range_end = 0.0f; + float visibility_range_begin_margin = 0.0f; + float visibility_range_end_margin = 0.0f; RS::VisibilityRangeFadeMode visibility_range_fade_mode = RS::VISIBILITY_RANGE_FADE_DISABLED; Instance *visibility_parent = nullptr; Set<Instance *> visibility_dependencies; - uint32_t visibility_dependencies_depth; - Scenario *scenario; + uint32_t visibility_dependencies_depth = 0; + float transparency = 0.0f; + Scenario *scenario = nullptr; SelfList<Instance> scenario_item; //aabb stuff @@ -1154,7 +1155,7 @@ public: /* Render Buffers */ PASS0R(RID, render_buffers_create) - PASS8(render_buffers_configure, RID, RID, int, int, RS::ViewportMSAA, RS::ViewportScreenSpaceAA, bool, uint32_t) + PASS12(render_buffers_configure, RID, RID, int, int, int, int, float, float, RS::ViewportMSAA, RS::ViewportScreenSpaceAA, bool, uint32_t) PASS1(gi_set_use_half_resolution, bool) /* Shadow Atlas */ diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h index 200ddc55d4..0d71ea22da 100644 --- a/servers/rendering/renderer_scene_render.h +++ b/servers/rendering/renderer_scene_render.h @@ -256,7 +256,7 @@ public: virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0; virtual RID render_buffers_create() = 0; - virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) = 0; + virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) = 0; virtual void gi_set_use_half_resolution(bool p_enable) = 0; virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0; diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h index 2985e05e8f..8926bf24aa 100644 --- a/servers/rendering/renderer_storage.h +++ b/servers/rendering/renderer_storage.h @@ -183,8 +183,8 @@ public: virtual String shader_get_code(RID p_shader) const = 0; virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0; - virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) = 0; - virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const = 0; + virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) = 0; + virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const = 0; virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const = 0; virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const = 0; diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index c3d57a13ad..eddf5bf53d 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -77,18 +77,69 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) { RSG::scene->free(p_viewport->render_buffers); p_viewport->render_buffers = RID(); } else { - float scale_3d = p_viewport->scale_3d; - if (Engine::get_singleton()->is_editor_hint()) { - // Ignore the 3D viewport render scaling inside of the editor. - // The Half Resolution 3D editor viewport option should be used instead. - scale_3d = 1.0; + float scaling_3d_scale = p_viewport->scaling_3d_scale; + + RS::ViewportScaling3DMode scaling_3d_mode = p_viewport->scaling_3d_mode; + bool scaling_enabled = true; + + if ((scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) && (scaling_3d_scale > 1.0)) { + // FSR is not design for downsampling. + // Throw a warning and fallback to VIEWPORT_SCALING_3D_MODE_BILINEAR + WARN_PRINT_ONCE("FSR 3D resolution scaling does not support supersampling. Falling back to bilinear scaling."); + scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_BILINEAR; } - // Clamp 3D rendering resolution to reasonable values supported on most hardware. - // This prevents freezing the engine or outright crashing on lower-end GPUs. - const int width = CLAMP(p_viewport->size.width * scale_3d, 1, 16384); - const int height = CLAMP(p_viewport->size.height * scale_3d, 1, 16384); - RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, width, height, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_debanding, p_viewport->get_view_count()); + if ((scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) && !p_viewport->fsr_enabled) { + // FSR is not actually available. + // Throw a warning and fallback to disable scaling + WARN_PRINT_ONCE("FSR 3D resolution scaling is not available. Disabling 3D resolution scaling."); + scaling_enabled = false; + } + + if (scaling_3d_scale == 1.0) { + scaling_enabled = false; + } + + int width; + int height; + int render_width; + int render_height; + + if (scaling_enabled) { + switch (scaling_3d_mode) { + case RS::VIEWPORT_SCALING_3D_MODE_BILINEAR: + // Clamp 3D rendering resolution to reasonable values supported on most hardware. + // This prevents freezing the engine or outright crashing on lower-end GPUs. + width = CLAMP(p_viewport->size.width * scaling_3d_scale, 1, 16384); + height = CLAMP(p_viewport->size.height * scaling_3d_scale, 1, 16384); + render_width = width; + render_height = height; + break; + case RS::VIEWPORT_SCALING_3D_MODE_FSR: + width = p_viewport->size.width; + height = p_viewport->size.height; + render_width = MAX(width * scaling_3d_scale, 1.0); // width / (width * scaling) + render_height = MAX(height * scaling_3d_scale, 1.0); + break; + default: + // This is an unknown mode. + WARN_PRINT_ONCE(vformat("Unknown scaling mode: %d. Disabling 3D resolution scaling.", scaling_3d_mode)); + width = p_viewport->size.width; + height = p_viewport->size.height; + render_width = width; + render_height = height; + break; + } + } else { + width = p_viewport->size.width; + height = p_viewport->size.height; + render_width = width; + render_height = height; + } + + p_viewport->internal_size = Size2(render_width, render_height); + + RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, render_width, render_height, width, height, p_viewport->fsr_sharpness, p_viewport->fsr_mipmap_bias, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_debanding, p_viewport->get_view_count()); } } } @@ -117,7 +168,7 @@ void RendererViewport::_draw_3d(Viewport *p_viewport) { } float screen_lod_threshold = p_viewport->lod_threshold / float(p_viewport->size.width); - RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->self, p_viewport->size, screen_lod_threshold, p_viewport->shadow_atlas, xr_interface, &p_viewport->render_info); + RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->self, p_viewport->internal_size, screen_lod_threshold, p_viewport->shadow_atlas, xr_interface, &p_viewport->render_info); RENDER_TIMESTAMP("<End Rendering 3D Scene"); } @@ -571,7 +622,7 @@ void RendererViewport::draw_viewports() { // override our size, make sure it matches our required size and is created as a stereo target vp->size = xr_interface->get_render_target_size(); uint32_t view_count = xr_interface->get_view_count(); - RSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y, view_count); + RSG::storage->render_target_set_size(vp->render_target, vp->internal_size.x, vp->internal_size.y, view_count); // check for an external texture destination (disabled for now, not yet supported) // RSG::storage->render_target_set_external_texture(vp->render_target, xr_interface->get_external_texture_for_eye(leftOrMono)); @@ -662,6 +713,8 @@ void RendererViewport::viewport_initialize(RID p_rid) { viewport->render_target = RSG::storage->render_target_create(); viewport->shadow_atlas = RSG::scene->shadow_atlas_create(); viewport->viewport_render_direct_to_screen = false; + + viewport->fsr_enabled = !RSG::rasterizer->is_low_end() && !viewport->disable_3d; } void RendererViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) { @@ -676,18 +729,42 @@ void RendererViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) { _configure_3d_render_buffers(viewport); } -void RendererViewport::viewport_set_scale_3d(RID p_viewport, float p_scale_3d) { +void RendererViewport::viewport_set_scaling_3d_mode(RID p_viewport, RS::ViewportScaling3DMode p_mode) { + Viewport *viewport = viewport_owner.get_or_null(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->scaling_3d_mode = p_mode; + _configure_3d_render_buffers(viewport); +} + +void RendererViewport::viewport_set_fsr_sharpness(RID p_viewport, float p_sharpness) { + Viewport *viewport = viewport_owner.get_or_null(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->fsr_sharpness = p_sharpness; + _configure_3d_render_buffers(viewport); +} + +void RendererViewport::viewport_set_fsr_mipmap_bias(RID p_viewport, float p_mipmap_bias) { + Viewport *viewport = viewport_owner.get_or_null(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->fsr_mipmap_bias = p_mipmap_bias; + _configure_3d_render_buffers(viewport); +} + +void RendererViewport::viewport_set_scaling_3d_scale(RID p_viewport, float p_scaling_3d_scale) { Viewport *viewport = viewport_owner.get_or_null(p_viewport); ERR_FAIL_COND(!viewport); // Clamp to reasonable values that are actually useful. // Values above 2.0 don't serve a practical purpose since the viewport // isn't displayed with mipmaps. - if (viewport->scale_3d == CLAMP(p_scale_3d, 0.1, 2.0)) { + if (viewport->scaling_3d_scale == CLAMP(p_scaling_3d_scale, 0.1, 2.0)) { return; } - viewport->scale_3d = CLAMP(p_scale_3d, 0.1, 2.0); + viewport->scaling_3d_scale = CLAMP(p_scaling_3d_scale, 0.1, 2.0); _configure_3d_render_buffers(viewport); } @@ -713,6 +790,7 @@ void RendererViewport::viewport_set_size(RID p_viewport, int p_width, int p_heig ERR_FAIL_COND(!viewport); viewport->size = Size2(p_width, p_height); + uint32_t view_count = viewport->get_view_count(); RSG::storage->render_target_set_size(viewport->render_target, p_width, p_height, view_count); _configure_3d_render_buffers(viewport); @@ -765,7 +843,7 @@ void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_ // if render_direct_to_screen was used, reset size and position if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) { RSG::storage->render_target_set_position(viewport->render_target, 0, 0); - RSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count()); + RSG::storage->render_target_set_size(viewport->render_target, viewport->internal_size.x, viewport->internal_size.y, viewport->get_view_count()); } viewport->viewport_to_screen_rect = Rect2(); diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h index f6e6cc8e84..5bb4dbbc6f 100644 --- a/servers/rendering/renderer_viewport.h +++ b/servers/rendering/renderer_viewport.h @@ -49,12 +49,16 @@ public: bool use_xr; /* use xr interface to override camera positioning and projection matrices and control output */ - float scale_3d = 1.0; - + Size2i internal_size; Size2i size; RID camera; RID scenario; + RS::ViewportScaling3DMode scaling_3d_mode; + float scaling_3d_scale = 1.0; + float fsr_sharpness = 0.2f; + float fsr_mipmap_bias = 0.0f; + bool fsr_enabled; RS::ViewportUpdateMode update_mode; RID render_target; RID render_target_texture; @@ -207,7 +211,6 @@ public: void viewport_initialize(RID p_rid); void viewport_set_use_xr(RID p_viewport, bool p_use_xr); - void viewport_set_scale_3d(RID p_viewport, float p_scale_3d); void viewport_set_size(RID p_viewport, int p_width, int p_height); @@ -216,6 +219,12 @@ public: void viewport_set_active(RID p_viewport, bool p_active); void viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport); + + void viewport_set_scaling_3d_mode(RID p_viewport, RS::ViewportScaling3DMode p_mode); + void viewport_set_scaling_3d_scale(RID p_viewport, float p_scaling_3d_scale); + void viewport_set_fsr_sharpness(RID p_viewport, float p_sharpness); + void viewport_set_fsr_mipmap_bias(RID p_viewport, float p_mipmap_bias); + void viewport_set_update_mode(RID p_viewport, RS::ViewportUpdateMode p_mode); void viewport_set_vflip(RID p_viewport, bool p_enable); diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index dcbc5f5c8e..5602bb197b 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -185,9 +185,13 @@ Ref<RDShaderSPIRV> RenderingDevice::_shader_compile_spirv_from_source(const Ref< String error; ShaderStage stage = ShaderStage(i); - Vector<uint8_t> spirv = shader_compile_spirv_from_source(stage, p_source->get_stage_source(stage), p_source->get_language(), &error, p_allow_cache); - bytecode->set_stage_bytecode(stage, spirv); - bytecode->set_stage_compile_error(stage, error); + String source = p_source->get_stage_source(stage); + + if (!source.is_empty()) { + Vector<uint8_t> spirv = shader_compile_spirv_from_source(stage, source, p_source->get_language(), &error, p_allow_cache); + bytecode->set_stage_bytecode(stage, spirv); + bytecode->set_stage_compile_error(stage, error); + } } return bytecode; } diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 5eb8f1cead..563a80c12c 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -120,6 +120,7 @@ public: // features bool supports_multiview = false; // If true this device supports multiview options + bool supports_fsr_half_float = false; // If true this device supports FSR scaling 3D in half float mode, otherwise use the fallback mode }; typedef String (*ShaderSPIRVGetCacheKeyFunction)(const Capabilities *p_capabilities); diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 9a592a9265..b50631bb21 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -223,8 +223,8 @@ public: FUNC2SC(shader_get_param_list, RID, List<PropertyInfo> *) - FUNC3(shader_set_default_texture_param, RID, const StringName &, RID) - FUNC2RC(RID, shader_get_default_texture_param, RID, const StringName &) + FUNC4(shader_set_default_texture_param, RID, const StringName &, RID, int) + FUNC3RC(RID, shader_get_default_texture_param, RID, const StringName &, int) FUNC2RC(Variant, shader_get_param_default, RID, const StringName &) FUNC1RC(ShaderNativeSourceCode, shader_get_native_source_code, RID) @@ -528,7 +528,6 @@ public: FUNCRIDSPLIT(viewport) FUNC2(viewport_set_use_xr, RID, bool) - FUNC2(viewport_set_scale_3d, RID, float) FUNC3(viewport_set_size, RID, int, int) FUNC2(viewport_set_active, RID, bool) @@ -539,6 +538,11 @@ public: FUNC3(viewport_attach_to_screen, RID, const Rect2 &, int) FUNC2(viewport_set_render_direct_to_screen, RID, bool) + FUNC2(viewport_set_scaling_3d_mode, RID, ViewportScaling3DMode) + FUNC2(viewport_set_scaling_3d_scale, RID, float) + FUNC2(viewport_set_fsr_sharpness, RID, float) + FUNC2(viewport_set_fsr_mipmap_bias, RID, float) + FUNC2(viewport_set_update_mode, RID, ViewportUpdateMode) FUNC1RC(RID, viewport_get_texture, RID) diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index d803d5fcf8..f5e91d0423 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -88,7 +88,8 @@ String ShaderLanguage::get_operator_text(Operator p_op) { "--", "()", "construct", - "index" }; + "index", + "empty" }; return op_names[p_op]; } @@ -474,6 +475,10 @@ ShaderLanguage::Token ShaderLanguage::_get_token() { case ':': return _make_token(TK_COLON); case '^': + if (GETCHAR(0) == '=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_BIT_XOR); + } return _make_token(TK_OP_BIT_XOR); case '~': return _make_token(TK_OP_BIT_INVERT); @@ -4293,7 +4298,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_size(BlockNode *p_block, cons return n; } -Error ShaderLanguage::_parse_global_array_size(int &r_array_size) { +Error ShaderLanguage::_parse_global_array_size(int &r_array_size, const FunctionInfo &p_function_info) { if (r_array_size > 0) { _set_error("Array size is already defined!"); return ERR_PARSE_ERROR; @@ -4305,7 +4310,7 @@ Error ShaderLanguage::_parse_global_array_size(int &r_array_size) { if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) { _set_tkpos(pos); - Node *n = _parse_array_size(nullptr, FunctionInfo(), array_size); + Node *n = _parse_array_size(nullptr, p_function_info, array_size); if (!n) { return ERR_PARSE_ERROR; } @@ -4920,7 +4925,9 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons bool error = false; Node *n = func->arguments[argidx]; if (n->type == Node::TYPE_CONSTANT || n->type == Node::TYPE_OPERATOR) { - error = true; + if (!call_function->arguments[i].is_const) { + error = true; + } } else if (n->type == Node::TYPE_ARRAY) { ArrayNode *an = static_cast<ArrayNode *>(n); if (an->call_expression != nullptr || an->is_const) { @@ -5206,9 +5213,21 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons expression.push_back(e); continue; } else { - _set_error("Expected expression, found: " + get_token_text(tk)); - return nullptr; - //nothing + if (tk.type != TK_SEMICOLON) { + _set_error("Expected expression, found: " + get_token_text(tk)); + return nullptr; + } else { +#if DEBUG_ENABLED + if (check_warnings && HAS_WARNING(ShaderWarning::FORMATTING_ERROR_FLAG)) { + _add_line_warning(ShaderWarning::FORMATTING_ERROR, "Empty statement. Remove ';' to fix this warning."); + } +#endif // DEBUG_ENABLED + _set_tkpos(prepos); + + OperatorNode *func = alloc_node<OperatorNode>(); + func->op = OP_EMPTY; + expr = func; + } } ERR_FAIL_COND_V(!expr, nullptr); @@ -6071,7 +6090,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons _set_error("Invalid arguments to unary operator '" + get_operator_text(op->op) + "' :" + at); return nullptr; } - expression.remove(i + 1); + expression.remove_at(i + 1); } } else if (is_ternary) { @@ -6111,7 +6130,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } for (int i = 0; i < 4; i++) { - expression.remove(next_op); + expression.remove_at(next_op); } } else { @@ -6172,8 +6191,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons return nullptr; } - expression.remove(next_op); - expression.remove(next_op); + expression.remove_at(next_op); + expression.remove_at(next_op); } } @@ -6384,7 +6403,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun ArrayDeclarationNode::Declaration adecl; if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) { - _set_error("Expected identifier or '[' after type."); + _set_error("Expected identifier or '[' after datatype."); return ERR_PARSE_ERROR; } @@ -7188,11 +7207,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun //check return type BlockNode *b = p_block; - if (b && b->parent_function && p_function_info.main_function) { - _set_error(vformat("Using 'return' in '%s' processor function results in undefined behavior!", b->parent_function->name)); - return ERR_PARSE_ERROR; - } - while (b && !b->parent_function) { b = b->parent_block; } @@ -7202,6 +7216,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun return ERR_BUG; } + if (b && b->parent_function && p_function_info.main_function) { + _set_error(vformat("Using 'return' in '%s' processor function results in undefined behavior!", b->parent_function->name)); + return ERR_PARSE_ERROR; + } + String return_struct_name = String(b->parent_function->return_struct_name); String array_size_string; @@ -7439,10 +7458,12 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct int texture_uniforms = 0; int texture_binding = 0; + int uniforms = 0; int instance_index = 0; ShaderNode::Uniform::Scope uniform_scope = ShaderNode::Uniform::SCOPE_LOCAL; stages = &p_functions; + const FunctionInfo &constants = p_functions.has("constants") ? p_functions["constants"] : FunctionInfo(); while (tk.type != TK_EOF) { switch (tk.type) { @@ -7486,7 +7507,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type == TK_IDENTIFIER) { st.name = tk.text; - if (shader->structs.has(st.name)) { + if (shader->constants.has(st.name) || shader->structs.has(st.name)) { _set_error("Redefinition of '" + String(st.name) + "'"); return ERR_PARSE_ERROR; } @@ -7558,7 +7579,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct int array_size = 0; if (tk.type == TK_BRACKET_OPEN) { - Error error = _parse_global_array_size(array_size); + Error error = _parse_global_array_size(array_size, constants); if (error != OK) { return error; } @@ -7585,7 +7606,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type == TK_BRACKET_OPEN) { - Error error = _parse_global_array_size(member->array_size); + Error error = _parse_global_array_size(member->array_size, constants); if (error != OK) { return error; } @@ -7712,7 +7733,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } if (tk.type == TK_BRACKET_OPEN) { - Error error = _parse_global_array_size(array_size); + Error error = _parse_global_array_size(array_size, constants); if (error != OK) { return error; } @@ -7727,7 +7748,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct prev_pos = _get_tkpos(); name = tk.text; - if (_find_identifier(nullptr, false, FunctionInfo(), name)) { + if (_find_identifier(nullptr, false, constants, name)) { _set_error("Redefinition of '" + String(name) + "'"); return ERR_PARSE_ERROR; } @@ -7760,7 +7781,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type == TK_BRACKET_OPEN) { - Error error = _parse_global_array_size(uniform2.array_size); + Error error = _parse_global_array_size(uniform2.array_size, constants); if (error != OK) { return error; } @@ -7789,6 +7810,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } uniform2.texture_order = -1; + if (uniform_scope != ShaderNode::Uniform::SCOPE_INSTANCE) { + uniform2.order = uniforms++; + } } if (uniform2.array_size > 0) { @@ -8011,7 +8035,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } - Node *expr = _parse_and_reduce_expression(nullptr, FunctionInfo()); + Node *expr = _parse_and_reduce_expression(nullptr, constants); if (!expr) { return ERR_PARSE_ERROR; } @@ -8107,7 +8131,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct DataPrecision precision = PRECISION_DEFAULT; DataType type; StringName name; - int return_array_size = 0; + int array_size = 0; if (tk.type == TK_CONST) { is_constant = true; @@ -8146,13 +8170,19 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct prev_pos = _get_tkpos(); tk = _get_token(); + bool unknown_size = false; + if (tk.type == TK_BRACKET_OPEN) { + if (is_constant && RenderingServer::get_singleton()->is_low_end()) { + _set_error("Global const arrays are only supported on high-end platform!"); + return ERR_PARSE_ERROR; + } bool error = false; tk = _get_token(); if (tk.type == TK_INT_CONSTANT) { - return_array_size = (int)tk.constant; - if (return_array_size > 0) { + array_size = (int)tk.constant; + if (array_size > 0) { tk = _get_token(); if (tk.type != TK_BRACKET_CLOSE) { _set_error("Expected ']'"); @@ -8161,11 +8191,13 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } else { error = true; } + } else if (tk.type == TK_BRACKET_CLOSE) { + unknown_size = true; } else { error = true; } if (error) { - _set_error("Expected integer constant > 0"); + _set_error("Expected integer constant > 0 or ']'"); return ERR_PARSE_ERROR; } @@ -8177,16 +8209,15 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct _get_completable_identifier(nullptr, COMPLETION_MAIN_FUNCTION, name); if (name == StringName()) { - _set_error("Expected function name after datatype"); - return ERR_PARSE_ERROR; - } - - if (_find_identifier(nullptr, false, FunctionInfo(), name)) { - _set_error("Redefinition of '" + String(name) + "'"); + if (is_constant) { + _set_error("Expected identifier or '[' after datatype."); + } else { + _set_error("Expected function name after datatype."); + } return ERR_PARSE_ERROR; } - if (has_builtin(p_functions, name)) { + if (shader->structs.has(name) || _find_identifier(nullptr, false, constants, name) || has_builtin(p_functions, name)) { _set_error("Redefinition of '" + String(name) + "'"); return ERR_PARSE_ERROR; } @@ -8199,7 +8230,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } //variable - + bool first = true; while (true) { ShaderNode::Constant constant; constant.name = name; @@ -8207,16 +8238,18 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct constant.type_str = struct_name; constant.precision = precision; constant.initializer = nullptr; - constant.array_size = 0; - - bool unknown_size = false; + constant.array_size = (first ? array_size : 0); + first = false; if (tk.type == TK_BRACKET_OPEN) { if (RenderingServer::get_singleton()->is_low_end()) { - _set_error("Global const arrays are supported only on high-end platform!"); + _set_error("Global const arrays are only supported on high-end platform!"); + return ERR_PARSE_ERROR; + } + if (constant.array_size > 0 || unknown_size) { + _set_error("Array size is already defined!"); return ERR_PARSE_ERROR; } - tk = _get_token(); if (tk.type == TK_BRACKET_CLOSE) { unknown_size = true; @@ -8294,7 +8327,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } else { _set_tkpos(prev_pos); - Node *n = _parse_and_reduce_expression(nullptr, FunctionInfo()); + Node *n = _parse_and_reduce_expression(nullptr, constants); if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) { _set_error("Expected single integer constant > 0"); return ERR_PARSE_ERROR; @@ -8375,7 +8408,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (tk.type == TK_PARENTHESIS_OPEN || curly) { // initialization while (true) { - Node *n = _parse_and_reduce_expression(nullptr, FunctionInfo()); + Node *n = _parse_and_reduce_expression(nullptr, constants); if (!n) { return ERR_PARSE_ERROR; } @@ -8430,7 +8463,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct constant.initializer = static_cast<ConstantNode *>(expr); } else { //variable created with assignment! must parse an expression - Node *expr = _parse_and_reduce_expression(nullptr, FunctionInfo()); + Node *expr = _parse_and_reduce_expression(nullptr, constants); if (!expr) { return ERR_PARSE_ERROR; } @@ -8446,7 +8479,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct constant.initializer = static_cast<ConstantNode *>(expr); - if (!_compare_datatypes(type, struct_name, 0, expr->get_datatype(), expr->get_datatype_name(), 0)) { + if (!_compare_datatypes(type, struct_name, 0, expr->get_datatype(), expr->get_datatype_name(), expr->get_array_size())) { return ERR_PARSE_ERROR; } } @@ -8477,7 +8510,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } name = tk.text; - if (_find_identifier(nullptr, false, FunctionInfo(), name)) { + if (_find_identifier(nullptr, false, constants, name)) { _set_error("Redefinition of '" + String(name) + "'"); return ERR_PARSE_ERROR; } @@ -8511,6 +8544,12 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } } + if (p_functions.has("constants")) { // Adds global constants: 'PI', 'TAU', 'E' + for (const KeyValue<StringName, BuiltInInfo> &E : p_functions["constants"].built_ins) { + builtins.built_ins.insert(E.key, E.value); + } + } + ShaderNode::Function function; function.callable = !p_functions.has(name); @@ -8526,7 +8565,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct func_node->return_type = type; func_node->return_struct_name = struct_name; func_node->return_precision = precision; - func_node->return_array_size = return_array_size; + func_node->return_array_size = array_size; if (p_functions.has(name)) { func_node->can_discard = p_functions[name].can_discard; @@ -8580,7 +8619,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct StringName param_struct_name; DataPrecision pprecision = PRECISION_DEFAULT; bool use_precision = false; - int array_size = 0; + int arg_array_size = 0; if (is_token_precision(tk.type)) { pprecision = get_token_precision(tk.type); @@ -8631,9 +8670,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type == TK_INT_CONSTANT) { - array_size = (int)tk.constant; + arg_array_size = (int)tk.constant; - if (array_size > 0) { + if (arg_array_size > 0) { tk = _get_token(); if (tk.type != TK_BRACKET_CLOSE) { _set_error("Expected ']'"); @@ -8685,7 +8724,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type == TK_BRACKET_OPEN) { - if (array_size > 0) { + if (arg_array_size > 0) { _set_error("Array size is already defined!"); return ERR_PARSE_ERROR; } @@ -8693,9 +8732,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type == TK_INT_CONSTANT) { - array_size = (int)tk.constant; + arg_array_size = (int)tk.constant; - if (array_size > 0) { + if (arg_array_size > 0) { tk = _get_token(); if (tk.type != TK_BRACKET_CLOSE) { _set_error("Expected ']'"); @@ -8715,7 +8754,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); } - arg.array_size = array_size; + arg.array_size = arg_array_size; func_node->arguments.push_back(arg); if (tk.type == TK_COMMA) { @@ -8767,20 +8806,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); } - int uniforms = 0; - - // Need to push arrays to first place in a uniform buffer in order to correct work. - for (Map<StringName, ShaderNode::Uniform>::Element *E = shader->uniforms.front(); E; E = E->next()) { - if (E->get().texture_order == -1 && E->get().scope != ShaderNode::Uniform::SCOPE_INSTANCE && E->get().array_size > 0) { - E->get().order = uniforms++; - } - } - for (Map<StringName, ShaderNode::Uniform>::Element *E = shader->uniforms.front(); E; E = E->next()) { - if (E->get().texture_order == -1 && E->get().scope != ShaderNode::Uniform::SCOPE_INSTANCE && E->get().array_size == 0) { - E->get().order = uniforms++; - } - } - int error_line; String error_message; if (!_check_varying_usages(&error_line, &error_message)) { @@ -9075,6 +9100,16 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct } } + if (p_functions.has("constants")) { + for (const KeyValue<StringName, BuiltInInfo> &E : p_functions["constants"].built_ins) { + ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER; + if (E.value.constant) { + kind = ScriptCodeCompletionOption::KIND_CONSTANT; + } + matches.insert(E.key, kind); + } + } + if (skip_function != StringName() && p_functions.has(skip_function)) { for (const KeyValue<StringName, BuiltInInfo> &E : p_functions[skip_function].built_ins) { ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER; diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index c82f71d10d..3de89a89a5 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -287,6 +287,7 @@ public: OP_CONSTRUCT, OP_STRUCT, OP_INDEX, + OP_EMPTY, OP_MAX }; @@ -989,7 +990,7 @@ private: bool _check_node_constness(const Node *p_node) const; Node *_parse_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, int &r_array_size); - Error _parse_global_array_size(int &r_array_size); + Error _parse_global_array_size(int &r_array_size, const FunctionInfo &p_function_info); Error _parse_local_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, ArrayDeclarationNode *p_node, ArrayDeclarationNode::Declaration *p_decl, int &r_array_size, bool &r_is_unknown_size); Node *_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info); diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index eb5c9e66e8..359196e096 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -59,9 +59,9 @@ ShaderTypes::ShaderTypes() { /*************** SPATIAL ***********************/ shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC3; shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3; @@ -241,9 +241,9 @@ ShaderTypes::ShaderTypes() { /************ CANVAS ITEM **************************/ shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC2; shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["UV"] = ShaderLanguage::TYPE_VEC2; @@ -334,9 +334,9 @@ ShaderTypes::ShaderTypes() { /************ PARTICLES **************************/ shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_PARTICLES].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_PARTICLES].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_PARTICLES].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4; shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["VELOCITY"] = ShaderLanguage::TYPE_VEC3; @@ -367,7 +367,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["LIFETIME"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["DELTA"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["NUMBER"] = constt(ShaderLanguage::TYPE_UINT); - shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_INT); + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_UINT); shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["EMISSION_TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["RANDOM_SEED"] = constt(ShaderLanguage::TYPE_UINT); shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["FLAG_EMIT_POSITION"] = constt(ShaderLanguage::TYPE_UINT); @@ -400,9 +400,9 @@ ShaderTypes::ShaderTypes() { /************ SKY **************************/ shader_modes[RS::SHADER_SKY].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_SKY].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_SKY].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_SKY].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_SKY].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_SKY].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_SKY].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_SKY].functions["global"].built_ins["POSITION"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_SKY].functions["global"].built_ins["RADIANCE"] = constt(ShaderLanguage::TYPE_SAMPLERCUBE); shader_modes[RS::SHADER_SKY].functions["global"].built_ins["AT_HALF_RES_PASS"] = constt(ShaderLanguage::TYPE_BOOL); @@ -446,9 +446,9 @@ ShaderTypes::ShaderTypes() { /************ FOG **************************/ shader_modes[RS::SHADER_FOG].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_FOG].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_FOG].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_FOG].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_FOG].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_FOG].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_FOG].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["WORLD_POSITION"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["OBJECT_POSITION"] = constt(ShaderLanguage::TYPE_VEC3); diff --git a/servers/rendering/shader_warnings.cpp b/servers/rendering/shader_warnings.cpp index 0b8476478c..bffae484a8 100644 --- a/servers/rendering/shader_warnings.cpp +++ b/servers/rendering/shader_warnings.cpp @@ -61,6 +61,8 @@ String ShaderWarning::get_message() const { return vformat("The varying '%s' is declared but never used.", subject); case UNUSED_LOCAL_VARIABLE: return vformat("The local variable '%s' is declared but never used.", subject); + case FORMATTING_ERROR: + return subject; default: break; } @@ -82,6 +84,7 @@ String ShaderWarning::get_name_from_code(Code p_code) { "UNUSED_UNIFORM", "UNUSED_VARYING", "UNUSED_LOCAL_VARIABLE", + "FORMATTING_ERROR", }; static_assert((sizeof(names) / sizeof(*names)) == WARNING_MAX, "Amount of warning types don't match the amount of warning names."); @@ -110,6 +113,7 @@ static void init_code_to_flags_map() { code_to_flags_map->insert(ShaderWarning::UNUSED_UNIFORM, ShaderWarning::UNUSED_UNIFORM_FLAG); code_to_flags_map->insert(ShaderWarning::UNUSED_VARYING, ShaderWarning::UNUSED_VARYING_FLAG); code_to_flags_map->insert(ShaderWarning::UNUSED_LOCAL_VARIABLE, ShaderWarning::UNUSED_LOCAL_VARIABLE_FLAG); + code_to_flags_map->insert(ShaderWarning::FORMATTING_ERROR, ShaderWarning::FORMATTING_ERROR_FLAG); } ShaderWarning::CodeFlags ShaderWarning::get_flags_from_codemap(const Map<Code, bool> &p_map) { diff --git a/servers/rendering/shader_warnings.h b/servers/rendering/shader_warnings.h index db872d8fb1..18915fffd8 100644 --- a/servers/rendering/shader_warnings.h +++ b/servers/rendering/shader_warnings.h @@ -47,6 +47,7 @@ public: UNUSED_UNIFORM, UNUSED_VARYING, UNUSED_LOCAL_VARIABLE, + FORMATTING_ERROR, WARNING_MAX, }; @@ -59,6 +60,7 @@ public: UNUSED_UNIFORM_FLAG = 16U, UNUSED_VARYING_FLAG = 32U, UNUSED_LOCAL_VARIABLE_FLAG = 64U, + FORMATTING_ERROR_FLAG = 128U, }; private: diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index cdf7fa530e..a23911e81a 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -199,11 +199,11 @@ RID RenderingServer::_make_test_cube() { normal_points[j][i % 3] = (i >= 3 ? -1 : 1); } - //tri 1 + // Tri 1 ADD_VTX(0); ADD_VTX(1); ADD_VTX(2); - //tri 2 + // Tri 2 ADD_VTX(2); ADD_VTX(3); ADD_VTX(0); @@ -317,9 +317,6 @@ RID RenderingServer::get_white_texture() { return white_texture; } -#define SMALL_VEC2 Vector2(0.00001, 0.00001) -#define SMALL_VEC3 Vector3(0.00001, 0.00001, 0.00001) - Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_vertex_stride, uint32_t p_attrib_stride, uint32_t p_skin_stride, Vector<uint8_t> &r_vertex_array, Vector<uint8_t> &r_attrib_array, Vector<uint8_t> &r_skin_array, int p_vertex_array_len, Vector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> &r_bone_aabb) { uint8_t *vw = r_vertex_array.ptrw(); uint8_t *aw = r_attrib_array.ptrw(); @@ -333,7 +330,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint int max_bone = 0; for (int ai = 0; ai < RS::ARRAY_MAX; ai++) { - if (!(p_format & (1 << ai))) { // no array + if (!(p_format & (1 << ai))) { // No array continue; } @@ -345,7 +342,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint const Vector2 *src = array.ptr(); - // setting vertices means regenerating the AABB + // Setting vertices means regenerating the AABB. Rect2 aabb; { @@ -355,7 +352,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], vector, sizeof(float) * 2); if (i == 0) { - aabb = Rect2(src[i], SMALL_VEC2); //must have a bit of size + aabb = Rect2(src[i], SMALL_VEC2); // Must have a bit of size. } else { aabb.expand_to(src[i]); } @@ -370,7 +367,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint const Vector3 *src = array.ptr(); - // setting vertices means regenerating the AABB + // Setting vertices means regenerating the AABB. AABB aabb; { @@ -505,7 +502,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint case ARRAY_CUSTOM_RGBA8_UNORM: case ARRAY_CUSTOM_RGBA8_SNORM: case ARRAY_CUSTOM_RG_HALF: { - //size 4 + // Size 4 ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_BYTE_ARRAY, ERR_INVALID_PARAMETER); Vector<uint8_t> array = p_arrays[ai]; @@ -520,7 +517,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint } break; case ARRAY_CUSTOM_RGBA_HALF: { - //size 8 + // Size 8 ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_BYTE_ARRAY, ERR_INVALID_PARAMETER); Vector<uint8_t> array = p_arrays[ai]; @@ -537,7 +534,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint case ARRAY_CUSTOM_RG_FLOAT: case ARRAY_CUSTOM_RGB_FLOAT: case ARRAY_CUSTOM_RGBA_FLOAT: { - //RF + // RF ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_FLOAT32_ARRAY, ERR_INVALID_PARAMETER); Vector<float> array = p_arrays[ai]; @@ -646,7 +643,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint } if (p_format & RS::ARRAY_FORMAT_BONES) { - //create AABBs for each detected bone + // Create AABBs for each detected bone. int total_bones = max_bone + 1; bool first = r_bone_aabb.size() == 0; @@ -657,7 +654,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint if (first) { for (int i = 0; i < total_bones; i++) { - r_bone_aabb.write[i].size = Vector3(-1, -1, -1); //negative means unused + r_bone_aabb.write[i].size = Vector3(-1, -1, -1); // Negative means unused. } } @@ -686,7 +683,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint ERR_FAIL_INDEX_V(idx, total_bones, ERR_INVALID_DATA); if (bptr[idx].size.x < 0) { - //first + // First bptr[idx] = AABB(v, SMALL_VEC3); any_valid = true; } else { @@ -749,7 +746,7 @@ void RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, i uint32_t *size_accum; for (int i = 0; i < RS::ARRAY_MAX; i++) { - r_offsets[i] = 0; //reset + r_offsets[i] = 0; // Reset if (i == RS::ARRAY_VERTEX) { size_accum = &r_vertex_element_size; @@ -759,7 +756,7 @@ void RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, i size_accum = &r_skin_element_size; } - if (!(p_format & (1 << i))) { // no array + if (!(p_format & (1 << i))) { // No array continue; } @@ -873,7 +870,7 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa uint32_t format = 0; - // validation + // Validation int index_array_len = 0; int array_len = 0; @@ -921,10 +918,10 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa } } - ERR_FAIL_COND_V((format & RS::ARRAY_FORMAT_VERTEX) == 0, ERR_INVALID_PARAMETER); // mandatory + ERR_FAIL_COND_V((format & RS::ARRAY_FORMAT_VERTEX) == 0, ERR_INVALID_PARAMETER); // Mandatory if (p_blend_shapes.size()) { - //validate format for morphs + // Validate format for morphs. for (int i = 0; i < p_blend_shapes.size(); i++) { uint32_t bsformat = 0; Array arr = p_blend_shapes[i]; @@ -939,7 +936,7 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa } for (uint32_t i = 0; i < RS::ARRAY_CUSTOM_COUNT; ++i) { - // include custom array format type. + // Include custom array format type. if (format & (1 << (ARRAY_CUSTOM0 + i))) { format |= (RS::ARRAY_FORMAT_CUSTOM_MASK << (RS::ARRAY_FORMAT_CUSTOM_BASE + i * RS::ARRAY_FORMAT_CUSTOM_BITS)) & p_compress_format; } @@ -954,7 +951,7 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa mesh_surface_make_offsets_from_format(format, array_len, index_array_len, offsets, vertex_element_size, attrib_element_size, skin_element_size); uint32_t mask = (1 << ARRAY_MAX) - 1; - format |= (~mask) & p_compress_format; //make the full format + format |= (~mask) & p_compress_format; // Make the full format. int vertex_array_size = vertex_element_size * array_len; int attrib_array_size = attrib_element_size * array_len; @@ -1010,13 +1007,13 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa Vector<int> indices = p_lods[E]; ERR_CONTINUE(indices.size() == 0); uint32_t index_count = indices.size(); - ERR_CONTINUE(index_count >= (uint32_t)index_array_len); //should be smaller.. + ERR_CONTINUE(index_count >= (uint32_t)index_array_len); // Should be smaller.. const int *r = indices.ptr(); Vector<uint8_t> data; if (array_len <= 65536) { - //16 bits indices + // 16 bits indices data.resize(indices.size() * 2); uint8_t *w = data.ptrw(); uint16_t *index_ptr = (uint16_t *)w; @@ -1024,7 +1021,7 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa index_ptr[i] = r[i]; } } else { - //32 bits indices + // 32 bits indices data.resize(indices.size() * 4); uint8_t *w = data.ptrw(); uint32_t *index_ptr = (uint32_t *)w; @@ -1204,7 +1201,7 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t case ARRAY_CUSTOM_RGBA8_SNORM: case ARRAY_CUSTOM_RG_HALF: case ARRAY_CUSTOM_RGBA_HALF: { - //size 4 + // Size 4 int s = type == ARRAY_CUSTOM_RGBA_HALF ? 8 : 4; Vector<uint8_t> arr; arr.resize(p_vertex_len * s); @@ -1472,12 +1469,12 @@ ShaderLanguage::DataType RenderingServer::global_variable_type_get_shader_dataty case RS::GLOBAL_VAR_TYPE_SAMPLERCUBE: return ShaderLanguage::TYPE_SAMPLERCUBE; default: - return ShaderLanguage::TYPE_MAX; //invalid or not found + return ShaderLanguage::TYPE_MAX; // Invalid or not found. } } RenderingDevice *RenderingServer::get_rendering_device() const { - // return the rendering device we're using globally + // Return the rendering device we're using globally. return RenderingDevice::get_singleton(); } @@ -1716,8 +1713,8 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("shader_get_param_list", "shader"), &RenderingServer::_shader_get_param_list); ClassDB::bind_method(D_METHOD("shader_get_param_default", "shader", "param"), &RenderingServer::shader_get_param_default); - ClassDB::bind_method(D_METHOD("shader_set_default_texture_param", "shader", "param", "texture"), &RenderingServer::shader_set_default_texture_param); - ClassDB::bind_method(D_METHOD("shader_get_default_texture_param", "shader", "param"), &RenderingServer::shader_get_default_texture_param); + ClassDB::bind_method(D_METHOD("shader_set_default_texture_param", "shader", "param", "texture", "index"), &RenderingServer::shader_set_default_texture_param, DEFVAL(0)); + ClassDB::bind_method(D_METHOD("shader_get_default_texture_param", "shader", "param", "index"), &RenderingServer::shader_get_default_texture_param, DEFVAL(0)); BIND_ENUM_CONSTANT(SHADER_SPATIAL); BIND_ENUM_CONSTANT(SHADER_CANVAS_ITEM); @@ -2165,13 +2162,16 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("viewport_create"), &RenderingServer::viewport_create); ClassDB::bind_method(D_METHOD("viewport_set_use_xr", "viewport", "use_xr"), &RenderingServer::viewport_set_use_xr); - ClassDB::bind_method(D_METHOD("viewport_set_scale_3d", "viewport", "scale"), &RenderingServer::viewport_set_scale_3d); ClassDB::bind_method(D_METHOD("viewport_set_size", "viewport", "width", "height"), &RenderingServer::viewport_set_size); ClassDB::bind_method(D_METHOD("viewport_set_active", "viewport", "active"), &RenderingServer::viewport_set_active); 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_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); + ClassDB::bind_method(D_METHOD("viewport_set_fsr_sharpness", "viewport", "sharpness"), &RenderingServer::viewport_set_fsr_sharpness); + ClassDB::bind_method(D_METHOD("viewport_set_fsr_mipmap_bias", "viewport", "mipmap_bias"), &RenderingServer::viewport_set_fsr_mipmap_bias); ClassDB::bind_method(D_METHOD("viewport_set_update_mode", "viewport", "update_mode"), &RenderingServer::viewport_set_update_mode); ClassDB::bind_method(D_METHOD("viewport_set_clear_mode", "viewport", "clear_mode"), &RenderingServer::viewport_set_clear_mode); ClassDB::bind_method(D_METHOD("viewport_get_texture", "viewport"), &RenderingServer::viewport_get_texture); @@ -2213,9 +2213,13 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("viewport_get_measured_render_time_gpu", "viewport"), &RenderingServer::viewport_get_measured_render_time_gpu); + BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_BILINEAR); + BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_FSR); + BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_MAX); + BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_DISABLED); - BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ONCE); //then goes to disabled); must be manually updated - BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_VISIBLE); // default + BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ONCE); // Then goes to disabled); must be manually updated. + BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_VISIBLE); // Default BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE); BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ALWAYS); @@ -2546,7 +2550,8 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("canvas_item_set_modulate", "item", "color"), &RenderingServer::canvas_item_set_modulate); ClassDB::bind_method(D_METHOD("canvas_item_set_self_modulate", "item", "color"), &RenderingServer::canvas_item_set_self_modulate); ClassDB::bind_method(D_METHOD("canvas_item_set_draw_behind_parent", "item", "enabled"), &RenderingServer::canvas_item_set_draw_behind_parent); - //primitives + + /* Primitives */ ClassDB::bind_method(D_METHOD("canvas_item_add_line", "item", "from", "to", "color", "width"), &RenderingServer::canvas_item_add_line, DEFVAL(1.0)); ClassDB::bind_method(D_METHOD("canvas_item_add_polyline", "item", "points", "colors", "width", "antialiased"), &RenderingServer::canvas_item_add_polyline, DEFVAL(1.0), DEFVAL(false)); @@ -2697,7 +2702,7 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_MAX); /* Free */ - ClassDB::bind_method(D_METHOD("free_rid", "rid"), &RenderingServer::free); // shouldn't conflict with Object::free() + ClassDB::bind_method(D_METHOD("free_rid", "rid"), &RenderingServer::free); // Shouldn't conflict with Object::free(). /* Misc */ @@ -2837,12 +2842,6 @@ RenderingServer::RenderingServer() { GLOBAL_DEF("rendering/vulkan/staging_buffer/texture_upload_region_size_px", 64); GLOBAL_DEF("rendering/vulkan/descriptor_pools/max_descriptors_per_pool", 64); - GLOBAL_DEF("rendering/3d/viewport/scale", 1.0); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/3d/viewport/scale", - PropertyInfo(Variant::FLOAT, - "rendering/3d/viewport/scale", - PROPERTY_HINT_RANGE, "0.25,2.0,0.01")); - GLOBAL_DEF("rendering/shader_compiler/shader_cache/enabled", true); GLOBAL_DEF("rendering/shader_compiler/shader_cache/compress", true); GLOBAL_DEF("rendering/shader_compiler/shader_cache/use_zstd_compression", true); @@ -2903,6 +2902,29 @@ RenderingServer::RenderingServer() { ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/screen_space_roughness_limiter/amount", PropertyInfo(Variant::FLOAT, "rendering/anti_aliasing/screen_space_roughness_limiter/amount", PROPERTY_HINT_RANGE, "0.01,4.0,0.01")); ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/screen_space_roughness_limiter/limit", PropertyInfo(Variant::FLOAT, "rendering/anti_aliasing/screen_space_roughness_limiter/limit", PROPERTY_HINT_RANGE, "0.01,1.0,0.01")); + GLOBAL_DEF_RST("rendering/scaling_3d/mode", 0); + GLOBAL_DEF_RST("rendering/scaling_3d/scale", 1.0); + GLOBAL_DEF_RST("rendering/scaling_3d/fsr_sharpness", 0.2f); + GLOBAL_DEF_RST("rendering/scaling_3d/fsr_mipmap_bias", 0.0f); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/scaling_3d/mode", + PropertyInfo(Variant::INT, + "rendering/scaling_3d/mode", + PROPERTY_HINT_ENUM, "Bilinear (Fastest),FSR (Fast)")); + + ProjectSettings::get_singleton()->set_custom_property_info("rendering/scaling_3d/scale", + PropertyInfo(Variant::FLOAT, + "rendering/scaling_3d/scale", + PROPERTY_HINT_RANGE, "0.25,2.0,0.01")); + + ProjectSettings::get_singleton()->set_custom_property_info("rendering/scaling_3d/fsr_sharpness", + PropertyInfo(Variant::FLOAT, + "rendering/scaling_3d/fsr_sharpness", + PROPERTY_HINT_RANGE, "0,2,0.1")); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/scaling_3d/fsr_mipmap_bias", + PropertyInfo(Variant::FLOAT, + "rendering/scaling_3d/fsr_mipmap_bias", + PROPERTY_HINT_RANGE, "-2,2,0.1")); + GLOBAL_DEF("rendering/textures/decals/filter", DECAL_FILTER_LINEAR_MIPMAPS); ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/decals/filter", PropertyInfo(Variant::INT, "rendering/textures/decals/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Nearest+Mipmaps,Linear,Linear+Mipmaps,Linear+Mipmaps Anisotropic (Slow)")); GLOBAL_DEF("rendering/textures/light_projectors/filter", LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index f35a633bf3..230132651f 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -55,6 +55,9 @@ class RenderingServer : public Object { RendererThreadPool *thread_pool = nullptr; + const Vector2 SMALL_VEC2 = Vector2(CMP_EPSILON, CMP_EPSILON); + const Vector3 SMALL_VEC3 = Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON); + protected: RID _make_test_cube(); void _free_internal_rids(); @@ -108,7 +111,7 @@ public: virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0; virtual void texture_proxy_update(RID p_texture, RID p_proxy_to) = 0; - //these two APIs can be used together or in combination with the others. + // These two APIs can be used together or in combination with the others. virtual RID texture_2d_placeholder_create() = 0; virtual RID texture_2d_layered_placeholder_create(TextureLayeredType p_layered_type) = 0; virtual RID texture_3d_placeholder_create() = 0; @@ -172,8 +175,8 @@ public: virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0; virtual Variant shader_get_param_default(RID p_shader, const StringName &p_param) const = 0; - virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) = 0; - virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const = 0; + virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index = 0) = 0; + virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index = 0) const = 0; struct ShaderNativeSourceCode { struct Version { @@ -210,18 +213,18 @@ public: enum ArrayType { ARRAY_VERTEX = 0, // RG32F or RGB32F (depending on 2D bit) - ARRAY_NORMAL = 1, // A2B10G10R10, A is ignored - ARRAY_TANGENT = 2, // A2B10G10R10, A flips sign of binormal + ARRAY_NORMAL = 1, // A2B10G10R10, A is ignored. + ARRAY_TANGENT = 2, // A2B10G10R10, A flips sign of binormal. ARRAY_COLOR = 3, // RGBA8 ARRAY_TEX_UV = 4, // RG32F ARRAY_TEX_UV2 = 5, // RG32F - ARRAY_CUSTOM0 = 6, // depends on ArrayCustomFormat + ARRAY_CUSTOM0 = 6, // Depends on ArrayCustomFormat. ARRAY_CUSTOM1 = 7, ARRAY_CUSTOM2 = 8, ARRAY_CUSTOM3 = 9, ARRAY_BONES = 10, // RGBA16UI (x2 if 8 weights) ARRAY_WEIGHTS = 11, // RGBA16UNORM (x2 if 8 weights) - ARRAY_INDEX = 12, // 16 or 32 bits depending on length > 0xFFFF + ARRAY_INDEX = 12, // 16 or 32 bits depending on length > 0xFFFF. ARRAY_MAX = 13 }; @@ -243,7 +246,7 @@ public: enum ArrayFormat { /* ARRAY FORMAT FLAGS */ - ARRAY_FORMAT_VERTEX = 1 << ARRAY_VERTEX, // mandatory + ARRAY_FORMAT_VERTEX = 1 << ARRAY_VERTEX, // Mandatory ARRAY_FORMAT_NORMAL = 1 << ARRAY_NORMAL, ARRAY_FORMAT_TANGENT = 1 << ARRAY_TANGENT, ARRAY_FORMAT_COLOR = 1 << ARRAY_COLOR, @@ -287,9 +290,9 @@ public: PrimitiveType primitive = PRIMITIVE_MAX; uint32_t format = 0; - Vector<uint8_t> vertex_data; // vertex, normal, tangent (change with skinning, blendshape) - Vector<uint8_t> attribute_data; // color,uv, uv2, custom0-3 - Vector<uint8_t> skin_data; // bone index, bone weight + Vector<uint8_t> vertex_data; // Vertex, Normal, Tangent (change with skinning, blendshape). + Vector<uint8_t> attribute_data; // Color, UV, UV2, Custom0-3. + Vector<uint8_t> skin_data; // Bone index, Bone weight. uint32_t vertex_count = 0; Vector<uint8_t> index_data; uint32_t index_count = 0; @@ -452,7 +455,7 @@ public: virtual void light_set_bake_mode(RID p_light, LightBakeMode p_bake_mode) = 0; virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) = 0; - // omni light + // Omni light enum LightOmniShadowMode { LIGHT_OMNI_SHADOW_DUAL_PARABOLOID, LIGHT_OMNI_SHADOW_CUBE, @@ -460,7 +463,7 @@ public: virtual void light_omni_set_shadow_mode(RID p_light, LightOmniShadowMode p_mode) = 0; - // directional light + // Directional light enum LightDirectionalShadowMode { LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL, LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS, @@ -671,7 +674,7 @@ public: virtual AABB particles_get_current_aabb(RID p_particles) = 0; - virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) = 0; //this is only used for 2D, in 3D it's automatic + virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) = 0; // This is only used for 2D, in 3D it's automatic. /* PARTICLES COLLISION API */ @@ -689,16 +692,16 @@ public: virtual void particles_collision_set_collision_type(RID p_particles_collision, ParticlesCollisionType p_type) = 0; virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) = 0; - virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) = 0; //for spheres - virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) = 0; //for non-spheres + virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) = 0; // For spheres. + virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) = 0; // For non-spheres. virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) = 0; virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) = 0; virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) = 0; - virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) = 0; //for SDF and vector field, heightfield is dynamic + virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) = 0; // For SDF and vector field, heightfield is dynamic. - virtual void particles_collision_height_field_update(RID p_particles_collision) = 0; //for SDF and vector field + virtual void particles_collision_height_field_update(RID p_particles_collision) = 0; // For SDF and vector field. - enum ParticlesCollisionHeightfieldResolution { //longest axis resolution + enum ParticlesCollisionHeightfieldResolution { // Longest axis resolution. PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_256, PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_512, PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024, @@ -708,7 +711,7 @@ public: PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX, }; - virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, ParticlesCollisionHeightfieldResolution p_resolution) = 0; //for SDF and vector field + virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, ParticlesCollisionHeightfieldResolution p_resolution) = 0; // For SDF and vector field. /* FOG VOLUME API */ @@ -750,7 +753,7 @@ public: /* VIEWPORT API */ enum CanvasItemTextureFilter { - CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, //uses canvas item setting for draw command, uses global setting for canvas item + CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, // Uses canvas item setting for draw command, uses global setting for canvas item. CANVAS_ITEM_TEXTURE_FILTER_NEAREST, CANVAS_ITEM_TEXTURE_FILTER_LINEAR, CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, @@ -761,7 +764,7 @@ public: }; enum CanvasItemTextureRepeat { - CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, //uses canvas item setting for draw command, uses global setting for canvas item + CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, // Uses canvas item setting for draw command, uses global setting for canvas item. CANVAS_ITEM_TEXTURE_REPEAT_DISABLED, CANVAS_ITEM_TEXTURE_REPEAT_ENABLED, CANVAS_ITEM_TEXTURE_REPEAT_MIRROR, @@ -770,8 +773,13 @@ public: virtual RID viewport_create() = 0; + enum ViewportScaling3DMode { + VIEWPORT_SCALING_3D_MODE_BILINEAR, + VIEWPORT_SCALING_3D_MODE_FSR, + VIEWPORT_SCALING_3D_MODE_MAX + }; + virtual void viewport_set_use_xr(RID p_viewport, bool p_use_xr) = 0; - virtual void viewport_set_scale_3d(RID p_viewport, float p_scale_3d) = 0; 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; @@ -779,10 +787,15 @@ public: 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; + virtual void viewport_set_scaling_3d_mode(RID p_viewport, ViewportScaling3DMode p_scaling_3d_mode) = 0; + virtual void viewport_set_scaling_3d_scale(RID p_viewport, float p_scaling_3d_scale) = 0; + virtual void viewport_set_fsr_sharpness(RID p_viewport, float p_fsr_sharpness) = 0; + virtual void viewport_set_fsr_mipmap_bias(RID p_viewport, float p_fsr_mipmap_bias) = 0; + enum ViewportUpdateMode { VIEWPORT_UPDATE_DISABLED, - VIEWPORT_UPDATE_ONCE, //then goes to disabled, must be manually updated - VIEWPORT_UPDATE_WHEN_VISIBLE, // default + VIEWPORT_UPDATE_ONCE, // Then goes to disabled, must be manually updated. + VIEWPORT_UPDATE_WHEN_VISIBLE, // Default VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE, VIEWPORT_UPDATE_ALWAYS }; @@ -1161,7 +1174,7 @@ public: virtual void instance_set_ignore_culling(RID p_instance, bool p_enabled) = 0; - // don't use these in a game! + // Don't use these in a game! virtual Vector<ObjectID> instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const = 0; virtual Vector<ObjectID> instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const = 0; virtual Vector<ObjectID> instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario = RID()) const = 0; @@ -1235,7 +1248,7 @@ public: virtual void canvas_texture_set_channel(RID p_canvas_texture, CanvasTextureChannel p_channel, RID p_texture) = 0; virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) = 0; - //takes effect only for new draw commands + // Takes effect only for new draw commands. virtual void canvas_texture_set_texture_filter(RID p_canvas_texture, CanvasItemTextureFilter p_filter) = 0; virtual void canvas_texture_set_texture_repeat(RID p_canvas_texture, CanvasItemTextureRepeat p_repeat) = 0; @@ -1433,7 +1446,7 @@ public: /* FREE */ - virtual void free(RID p_rid) = 0; ///< free RIDs associated with the rendering server + virtual void free(RID p_rid) = 0; // Free RIDs associated with the rendering server. /* EVENT QUEUING */ @@ -1519,7 +1532,7 @@ public: virtual ~RenderingServer(); private: - //binder helpers + // Binder helpers RID _texture_2d_layered_create(const TypedArray<Image> &p_layers, TextureLayeredType p_layered_type); RID _texture_3d_create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const TypedArray<Image> &p_data); void _texture_3d_update(RID p_texture, const TypedArray<Image> &p_data); @@ -1533,7 +1546,7 @@ private: void _particles_set_trail_bind_poses(RID p_particles, const TypedArray<Transform3D> &p_bind_poses); }; -// make variant understand the enums +// Make variant understand the enums. VARIANT_ENUM_CAST(RenderingServer::TextureLayeredType); VARIANT_ENUM_CAST(RenderingServer::CubeMapLayer); VARIANT_ENUM_CAST(RenderingServer::ShaderMode); @@ -1561,6 +1574,7 @@ VARIANT_ENUM_CAST(RenderingServer::ParticlesEmitFlags); VARIANT_ENUM_CAST(RenderingServer::ParticlesCollisionType); VARIANT_ENUM_CAST(RenderingServer::ParticlesCollisionHeightfieldResolution); VARIANT_ENUM_CAST(RenderingServer::FogVolumeShape); +VARIANT_ENUM_CAST(RenderingServer::ViewportScaling3DMode); VARIANT_ENUM_CAST(RenderingServer::ViewportUpdateMode); VARIANT_ENUM_CAST(RenderingServer::ViewportClearMode); VARIANT_ENUM_CAST(RenderingServer::ViewportMSAA); diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp index 0a7523e33a..d6d98b4f8f 100644 --- a/servers/text/text_server_extension.cpp +++ b/servers/text/text_server_extension.cpp @@ -260,6 +260,7 @@ void TextServerExtension::_bind_methods() { GDVIRTUAL_BIND(_shaped_text_draw, "shaped", "canvas", "pos", "clip_l", "clip_r", "color"); GDVIRTUAL_BIND(_shaped_text_draw_outline, "shaped", "canvas", "pos", "clip_l", "clip_r", "outline_size", "color"); + GDVIRTUAL_BIND(_shaped_text_get_grapheme_bounds, "shaped", "pos"); GDVIRTUAL_BIND(_shaped_text_next_grapheme_pos, "shaped", "pos"); GDVIRTUAL_BIND(_shaped_text_prev_grapheme_pos, "shaped", "pos"); @@ -1292,6 +1293,14 @@ void TextServerExtension::shaped_text_draw_outline(RID p_shaped, RID p_canvas, c shaped_text_draw_outline(p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_outline_size, p_color); } +Vector2 TextServerExtension::shaped_text_get_grapheme_bounds(RID p_shaped, int p_pos) const { + Vector2 ret; + if (GDVIRTUAL_CALL(_shaped_text_get_grapheme_bounds, p_shaped, p_pos, ret)) { + return ret; + } + return TextServer::shaped_text_get_grapheme_bounds(p_shaped, p_pos); +} + int TextServerExtension::shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const { int ret; if (GDVIRTUAL_CALL(_shaped_text_next_grapheme_pos, p_shaped, p_pos, ret)) { diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h index e419b4055d..a2dbd25e05 100644 --- a/servers/text/text_server_extension.h +++ b/servers/text/text_server_extension.h @@ -428,8 +428,10 @@ public: GDVIRTUAL6C(_shaped_text_draw, RID, RID, const Vector2 &, float, float, const Color &); GDVIRTUAL7C(_shaped_text_draw_outline, RID, RID, const Vector2 &, float, float, int, const Color &); + virtual Vector2 shaped_text_get_grapheme_bounds(RID p_shaped, int p_pos) const override; virtual int shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const override; virtual int shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) const override; + GDVIRTUAL2RC(Vector2, _shaped_text_get_grapheme_bounds, RID, int); GDVIRTUAL2RC(int, _shaped_text_next_grapheme_pos, RID, int); GDVIRTUAL2RC(int, _shaped_text_prev_grapheme_pos, RID, int); diff --git a/servers/text_server.cpp b/servers/text_server.cpp index 9034239fe0..3b71dc1d92 100644 --- a/servers/text_server.cpp +++ b/servers/text_server.cpp @@ -78,7 +78,7 @@ void TextServerManager::remove_interface(const Ref<TextServer> &p_interface) { ERR_FAIL_COND(idx == -1); print_verbose("TextServer: Removed interface \"" + p_interface->get_name() + "\""); emit_signal(SNAME("interface_removed"), p_interface->get_name()); - interfaces.remove(idx); + interfaces.remove_at(idx); } int TextServerManager::get_interface_count() const { @@ -141,7 +141,7 @@ TextServerManager::~TextServerManager() { primary_interface.unref(); } while (interfaces.size() > 0) { - interfaces.remove(0); + interfaces.remove_at(0); } singleton = nullptr; } @@ -403,6 +403,7 @@ void TextServer::_bind_methods() { ClassDB::bind_method(D_METHOD("shaped_text_hit_test_grapheme", "shaped", "coords"), &TextServer::shaped_text_hit_test_grapheme); ClassDB::bind_method(D_METHOD("shaped_text_hit_test_position", "shaped", "coords"), &TextServer::shaped_text_hit_test_position); + ClassDB::bind_method(D_METHOD("shaped_text_get_grapheme_bounds", "shaped", "pos"), &TextServer::shaped_text_get_grapheme_bounds); ClassDB::bind_method(D_METHOD("shaped_text_next_grapheme_pos", "shaped", "pos"), &TextServer::shaped_text_next_grapheme_pos); ClassDB::bind_method(D_METHOD("shaped_text_prev_grapheme_pos", "shaped", "pos"), &TextServer::shaped_text_prev_grapheme_pos); @@ -1023,7 +1024,7 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start, while (j < ranges.size()) { if (Math::is_equal_approx(ranges[i].y, ranges[j].x, (real_t)UNIT_EPSILON)) { ranges.write[i].y = ranges[j].y; - ranges.remove(j); + ranges.remove_at(j); continue; } j++; @@ -1120,6 +1121,27 @@ int TextServer::shaped_text_hit_test_position(RID p_shaped, real_t p_coords) con return 0; } +Vector2 TextServer::shaped_text_get_grapheme_bounds(RID p_shaped, int p_pos) const { + int v_size = shaped_text_get_glyph_count(p_shaped); + const Glyph *glyphs = shaped_text_get_glyphs(p_shaped); + + real_t off = 0.0f; + for (int i = 0; i < v_size; i++) { + if ((glyphs[i].count > 0) && ((glyphs[i].index != 0) || ((glyphs[i].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE))) { + if (glyphs[i].start <= p_pos && glyphs[i].end >= p_pos) { + real_t advance = 0.f; + for (int j = 0; j < glyphs[i].count; j++) { + advance += glyphs[i + j].advance; + } + return Vector2(off, off + advance); + } + } + off += glyphs[i].advance * glyphs[i].repeat; + } + + return Vector2(); +} + int TextServer::shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const { int v_size = shaped_text_get_glyph_count(p_shaped); const Glyph *glyphs = shaped_text_get_glyphs(p_shaped); diff --git a/servers/text_server.h b/servers/text_server.h index 4f55f881e6..5c994feaae 100644 --- a/servers/text_server.h +++ b/servers/text_server.h @@ -438,6 +438,7 @@ public: virtual int shaped_text_hit_test_grapheme(RID p_shaped, float p_coords) const; // Return grapheme index. virtual int shaped_text_hit_test_position(RID p_shaped, float p_coords) const; // Return caret/selection position. + virtual Vector2 shaped_text_get_grapheme_bounds(RID p_shaped, int p_pos) const; virtual int shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const; virtual int shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) const; diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp index d0367ba95e..959288497d 100644 --- a/servers/xr_server.cpp +++ b/servers/xr_server.cpp @@ -193,7 +193,7 @@ void XRServer::remove_interface(const Ref<XRInterface> &p_interface) { print_verbose("XR: Removed interface" + p_interface->get_name()); emit_signal(SNAME("interface_removed"), p_interface->get_name()); - interfaces.remove(idx); + interfaces.remove_at(idx); }; int XRServer::get_interface_count() const { @@ -396,7 +396,7 @@ XRServer::~XRServer() { primary_interface.unref(); while (interfaces.size() > 0) { - interfaces.remove(0); + interfaces.remove_at(0); } // TODO pretty sure there is a clear function or something... |