diff options
Diffstat (limited to 'scene/resources/particle_process_material.cpp')
-rw-r--r-- | scene/resources/particle_process_material.cpp | 43 |
1 files changed, 18 insertions, 25 deletions
diff --git a/scene/resources/particle_process_material.cpp b/scene/resources/particle_process_material.cpp index 0b65b33240..01d26a8bed 100644 --- a/scene/resources/particle_process_material.cpp +++ b/scene/resources/particle_process_material.cpp @@ -33,14 +33,12 @@ #include "core/version.h" Mutex ParticleProcessMaterial::material_mutex; -SelfList<ParticleProcessMaterial>::List *ParticleProcessMaterial::dirty_materials = nullptr; +SelfList<ParticleProcessMaterial>::List ParticleProcessMaterial::dirty_materials; HashMap<ParticleProcessMaterial::MaterialKey, ParticleProcessMaterial::ShaderData, ParticleProcessMaterial::MaterialKey> ParticleProcessMaterial::shader_map; RBSet<String> ParticleProcessMaterial::min_max_properties; ParticleProcessMaterial::ShaderNames *ParticleProcessMaterial::shader_names = nullptr; void ParticleProcessMaterial::init_shaders() { - dirty_materials = memnew(SelfList<ParticleProcessMaterial>::List); - shader_names = memnew(ShaderNames); shader_names->direction = "direction"; @@ -140,15 +138,13 @@ void ParticleProcessMaterial::init_shaders() { } void ParticleProcessMaterial::finish_shaders() { - memdelete(dirty_materials); - dirty_materials = nullptr; + dirty_materials.clear(); memdelete(shader_names); + shader_names = nullptr; } void ParticleProcessMaterial::_update_shader() { - dirty_materials->remove(&element); - MaterialKey mk = _compute_key(); if (mk == current_key) { return; //no update required in the end @@ -634,7 +630,7 @@ void ParticleProcessMaterial::_update_shader() { if (emission_shape == EMISSION_SHAPE_RING) { code += " \n"; code += " float ring_spawn_angle = rand_from_seed(alt_seed) * 2.0 * pi;\n"; - code += " float ring_random_radius = sqrt(rand_from_seed(alt_seed) * (emission_ring_radius - emission_ring_inner_radius * emission_ring_inner_radius) + emission_ring_inner_radius * emission_ring_inner_radius);\n"; + code += " float ring_random_radius = sqrt(rand_from_seed(alt_seed) * (emission_ring_radius * emission_ring_radius - emission_ring_inner_radius * emission_ring_inner_radius) + emission_ring_inner_radius * emission_ring_inner_radius);\n"; code += " vec3 axis = emission_ring_axis == vec3(0.0) ? vec3(0.0, 0.0, 1.0) : normalize(emission_ring_axis);\n"; code += " vec3 ortho_axis = vec3(0.0);\n"; code += " if (abs(axis) == vec3(1.0, 0.0, 0.0)) {\n"; @@ -995,13 +991,15 @@ void ParticleProcessMaterial::_update_shader() { code += " \n"; if (collision_mode == COLLISION_RIGID) { code += " if (COLLIDED) {\n"; - code += " if (length(VELOCITY) > 3.0) {\n"; - code += " TRANSFORM[3].xyz += COLLISION_NORMAL * COLLISION_DEPTH;\n"; - code += " VELOCITY -= COLLISION_NORMAL * dot(COLLISION_NORMAL, VELOCITY) * (1.0 + collision_bounce);\n"; - code += " VELOCITY = mix(VELOCITY,vec3(0.0),clamp(collision_friction, 0.0, 1.0));\n"; - code += " } else {\n"; - code += " VELOCITY = vec3(0.0);\n"; - code += " }\n"; + code += " float collision_response = dot(COLLISION_NORMAL, VELOCITY);\n"; + code += " float slide_to_bounce_trigger = step(2.0/clamp(collision_bounce + 1.0, 1.0, 2.0), abs(collision_response));\n"; + code += " TRANSFORM[3].xyz += COLLISION_NORMAL * COLLISION_DEPTH;\n"; + code += " // Remove all components of VELOCITY that is not tangent to COLLISION_NORMAL\n"; + code += " VELOCITY -= COLLISION_NORMAL * collision_response;\n"; + code += " // Apply friction only to VELOCITY across the surface (Effectively decouples friction and bounce behavior).\n"; + code += " VELOCITY = mix(VELOCITY,vec3(0.0),clamp(collision_friction, 0.0, 1.0));\n"; + code += " // Add bounce velocity to VELOCITY\n"; + code += " VELOCITY -= COLLISION_NORMAL * collision_response * (collision_bounce * slide_to_bounce_trigger);\n"; code += " }\n"; } else if (collision_mode == COLLISION_HIDE_ON_CONTACT) { code += " if (COLLIDED) {\n"; @@ -1170,8 +1168,9 @@ void ParticleProcessMaterial::_update_shader() { void ParticleProcessMaterial::flush_changes() { MutexLock lock(material_mutex); - while (dirty_materials->first()) { - dirty_materials->first()->self()->_update_shader(); + while (dirty_materials.first()) { + dirty_materials.first()->self()->_update_shader(); + dirty_materials.first()->remove_from_list(); } } @@ -1179,16 +1178,10 @@ void ParticleProcessMaterial::_queue_shader_change() { MutexLock lock(material_mutex); if (_is_initialized() && !element.in_list()) { - dirty_materials->add(&element); + dirty_materials.add(&element); } } -bool ParticleProcessMaterial::_is_shader_dirty() const { - MutexLock lock(material_mutex); - - return element.in_list(); -} - bool ParticleProcessMaterial::has_min_max_property(const String &p_name) { return min_max_properties.has(p_name); } @@ -2330,7 +2323,7 @@ ParticleProcessMaterial::ParticleProcessMaterial() : current_key.invalid_key = 1; - _mark_initialized(callable_mp(this, &ParticleProcessMaterial::_queue_shader_change)); + _mark_initialized(callable_mp(this, &ParticleProcessMaterial::_queue_shader_change), callable_mp(this, &ParticleProcessMaterial::_update_shader)); } ParticleProcessMaterial::~ParticleProcessMaterial() { |