diff options
Diffstat (limited to 'servers')
50 files changed, 598 insertions, 364 deletions
diff --git a/servers/physics_2d/godot_area_2d.cpp b/servers/physics_2d/godot_area_2d.cpp index 6983e28841..fb9d38e7ea 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: 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..a98513004d 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()) { diff --git a/servers/physics_2d/godot_area_pair_2d.h b/servers/physics_2d/godot_area_pair_2d.h index 7a9677f714..45bd3df1ed 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: diff --git a/servers/physics_2d/godot_body_2d.cpp b/servers/physics_2d/godot_body_2d.cpp index 442c580920..9b97583300 100644 --- a/servers/physics_2d/godot_body_2d.cpp +++ b/servers/physics_2d/godot_body_2d.cpp @@ -410,15 +410,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 +419,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 +439,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. diff --git a/servers/physics_2d/godot_body_2d.h b/servers/physics_2d/godot_body_2d.h index 7b11b50739..d1dbf92c1b 100644 --- a/servers/physics_2d/godot_body_2d.h +++ b/servers/physics_2d/godot_body_2d.h @@ -145,8 +145,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 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..6465a5542c 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); diff --git a/servers/physics_3d/godot_area_3d.cpp b/servers/physics_3d/godot_area_3d.cpp index 973fc50968..9cdad069fe 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: 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..d3623178d5 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()) { @@ -207,10 +215,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 +239,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 +247,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 +274,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..16175e9fa8 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; @@ -79,6 +80,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..0e21dd303f 100644 --- a/servers/physics_3d/godot_body_3d.cpp +++ b/servers/physics_3d/godot_body_3d.cpp @@ -457,15 +457,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 +474,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 +494,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. diff --git a/servers/physics_3d/godot_body_3d.h b/servers/physics_3d/godot_body_3d.h index 7fc2f58168..ac3131ab44 100644 --- a/servers/physics_3d/godot_body_3d.h +++ b/servers/physics_3d/godot_body_3d.h @@ -139,8 +139,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 diff --git a/servers/physics_3d/godot_body_pair_3d.cpp b/servers/physics_3d/godot_body_pair_3d.cpp index f7d9ed9ee9..f0002870ae 100644 --- a/servers/physics_3d/godot_body_pair_3d.cpp +++ b/servers/physics_3d/godot_body_pair_3d.cpp @@ -191,7 +191,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; } diff --git a/servers/physics_3d/godot_collision_solver_3d.cpp b/servers/physics_3d/godot_collision_solver_3d.cpp index b9f2f7506b..686f3e4d59 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; } 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..b520ee45c7 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); @@ -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; @@ -1675,7 +1675,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 +1881,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 +1899,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; diff --git a/servers/physics_3d/godot_shape_3d.h b/servers/physics_3d/godot_shape_3d.h index 1bbcd903f7..7a32b69166 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; @@ -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,7 +366,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 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; @@ -429,7 +429,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 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; @@ -456,7 +456,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 +495,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..b8e9ab4fb9 100644 --- a/servers/physics_3d/godot_soft_body_3d.cpp +++ b/servers/physics_3d/godot_soft_body_3d.cpp @@ -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++) { @@ -1004,44 +987,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(); - int ac = areas.size(); - bool stopped = false; - bool has_wind_forces = false; + + bool gravity_done = false; + + LocalVector<GodotArea3D *> wind_areas; 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 +1298,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..c03951959f 100644 --- a/servers/physics_3d/godot_soft_body_3d.h +++ b/servers/physics_3d/godot_soft_body_3d.h @@ -232,7 +232,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 +257,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..e2f90b90ad 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); 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..2bff8f5dcb 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; }; 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..89a7eeee96 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; }; 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..cecb009aa0 100644 --- a/servers/rendering/rasterizer_dummy.h +++ b/servers/rendering/rasterizer_dummy.h @@ -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_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index b74d7f9c31..6ae76c9bf2 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; } } 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/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index 16d650a540..3a6c945052 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; } } 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..81a662c6eb 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -2120,11 +2120,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_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 0ca2f051fa..b8e9f40bc4 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -2086,7 +2086,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,7 +2102,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende EffectsRD::BokehBuffers buffers; - // textures we use + // Textures we use. buffers.base_texture_size = Size2i(rb->width, rb->height); buffers.base_texture = rb->texture; buffers.depth_texture = rb->depth_texture; @@ -2114,7 +2114,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 +2124,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); @@ -2147,13 +2147,13 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende } 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); } - //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(); } @@ -2207,7 +2207,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()) { @@ -2246,6 +2245,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); @@ -2280,6 +2283,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 +2298,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. @@ -3549,11 +3558,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; } } diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index baa0144d43..740e0e75ce 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -879,12 +879,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; 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..64be176d24 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -1440,8 +1440,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 +1473,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 +1500,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(); @@ -2610,7 +2621,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 +2684,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 +2844,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()) { @@ -5748,11 +5759,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; } } diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h index f13bd4a7f4..2cd3a01c66 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: @@ -374,7 +374,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 +883,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; @@ -1414,8 +1414,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/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl index 4119e98d15..83c02d08a7 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl @@ -1529,7 +1529,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 +1540,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 +1548,6 @@ void main() { #ifdef LIGHT_ANISOTROPY_USED binormal, tangent, anisotropy, #endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif diffuse_light, specular_light); } @@ -1603,7 +1600,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 +1612,6 @@ void main() { #ifdef LIGHT_RIM_USED rim, rim_tint, - albedo, #endif #ifdef LIGHT_CLEARCOAT_USED clearcoat, clearcoat_gloss, @@ -1623,9 +1619,6 @@ void main() { #ifdef LIGHT_ANISOTROPY_USED tangent, binormal, anisotropy, #endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif diffuse_light, specular_light); } } @@ -1679,7 +1672,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 +1684,6 @@ void main() { #ifdef LIGHT_RIM_USED rim, rim_tint, - albedo, #endif #ifdef LIGHT_CLEARCOAT_USED clearcoat, clearcoat_gloss, @@ -1699,9 +1691,6 @@ void main() { #ifdef LIGHT_ANISOTROPY_USED tangent, binormal, anisotropy, #endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif diffuse_light, specular_light); } } 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..e2fec87d2a 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl @@ -1395,7 +1395,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 +1409,6 @@ void main() { #ifdef LIGHT_RIM_USED rim, rim_tint, - albedo, #endif #ifdef LIGHT_CLEARCOAT_USED clearcoat, clearcoat_gloss, @@ -1417,9 +1416,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 +1439,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 +1453,6 @@ void main() { #ifdef LIGHT_RIM_USED rim, rim_tint, - albedo, #endif #ifdef LIGHT_CLEARCOAT_USED clearcoat, clearcoat_gloss, @@ -1465,9 +1460,6 @@ void main() { #ifdef LIGHT_ANISOTROPY_USED tangent, binormal, anisotropy, #endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif diffuse_light, specular_light); } } //spot lights 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/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 9a592a9265..f75bca600e 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) diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index cdf7fa530e..ae72f47a44 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -1716,8 +1716,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); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index f35a633bf3..32ec0197ee 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -172,8 +172,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 { |