Fix particle jitter when scene tree is paused.

(cherry picked from commit 87efa4d210)
This commit is contained in:
Evan Todd
2024-08-21 10:42:37 -07:00
committed by Rémi Verschelde
parent 290b3247eb
commit a241eb32d4
3 changed files with 21 additions and 41 deletions

View File

@ -513,7 +513,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
double new_phase = Math::fmod(p_particles->phase + (p_delta / p_particles->lifetime) * p_particles->speed_scale, 1.0);
double new_phase = Math::fmod(p_particles->phase + (p_delta / p_particles->lifetime), 1.0);
//update current frame
ParticlesFrameParams frame_params;
@ -534,7 +534,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
p_particles->phase = new_phase;
frame_params.time = RSG::rasterizer->get_total_time();
frame_params.delta = p_delta * p_particles->speed_scale;
frame_params.delta = p_delta;
frame_params.random_seed = p_particles->random_seed;
frame_params.explosiveness = p_particles->explosiveness;
frame_params.randomness = p_particles->randomness;
@ -1097,8 +1097,6 @@ void ParticlesStorage::update_particles() {
fixed_fps = particles->fixed_fps;
}
bool zero_time_scale = Engine::get_singleton()->get_time_scale() <= 0.0;
if (particles->clear && particles->pre_process_time > 0.0) {
double frame_time;
if (fixed_fps > 0) {
@ -1115,37 +1113,27 @@ void ParticlesStorage::update_particles() {
}
}
double time_scale = MAX(particles->speed_scale, 0.0);
if (fixed_fps > 0) {
double frame_time;
double decr;
if (zero_time_scale) {
frame_time = 0.0;
decr = 1.0 / fixed_fps;
} else {
frame_time = 1.0 / fixed_fps;
decr = frame_time;
}
double frame_time = 1.0 / fixed_fps;
double delta = RSG::rasterizer->get_frame_delta_time();
if (delta > 0.1) { //avoid recursive stalls if fps goes below 10
delta = 0.1;
} else if (delta <= 0.0) { //unlikely but..
delta = 0.001;
}
double todo = particles->frame_remainder + delta;
double todo = particles->frame_remainder + delta * time_scale;
while (todo >= frame_time) {
_particles_process(particles, frame_time);
todo -= decr;
todo -= frame_time;
}
particles->frame_remainder = todo;
} else {
if (zero_time_scale) {
_particles_process(particles, 0.0);
} else {
_particles_process(particles, RSG::rasterizer->get_frame_delta_time());
}
_particles_process(particles, RSG::rasterizer->get_frame_delta_time() * time_scale);
}
if (particles->request_process_time > 0.0) {

View File

@ -1034,7 +1034,7 @@ void ParticleProcessMaterial::_update_shader() {
code += " {\n";
}
code += " float vel_mag = length(VELOCITY);\n";
code += " float vel_infl = clamp(dynamic_params.turb_influence * turbulence_influence, 0.0, 1.0);\n";
code += " float vel_infl = clamp(dynamic_params.turb_influence * turbulence_influence, 0.0, 1.0) * (DELTA <= 0.0 ? 0.0 : 1.0);\n";
code += " VELOCITY = mix(VELOCITY, normalize(noise_direction) * vel_mag * (1.0 + (1.0 - vel_infl) * 0.2), vel_infl);\n";
code += " vel_mag = length(controlled_displacement);\n";
code += " controlled_displacement = mix(controlled_displacement, normalize(noise_direction) * vel_mag * (1.0 + (1.0 - vel_infl) * 0.2), vel_infl);\n";

View File

@ -814,7 +814,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
p_particles->particles_material_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 1);
}
double new_phase = Math::fmod((double)p_particles->phase + (p_delta / p_particles->lifetime) * p_particles->speed_scale, 1.0);
double new_phase = Math::fmod((double)p_particles->phase + (p_delta / p_particles->lifetime), 1.0);
//move back history (if there is any)
for (uint32_t i = p_particles->frame_history.size() - 1; i > 0; i--) {
@ -839,7 +839,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
p_particles->phase = new_phase;
frame_params.time = RendererCompositorRD::get_singleton()->get_total_time();
frame_params.delta = p_delta * p_particles->speed_scale;
frame_params.delta = p_delta;
frame_params.random_seed = p_particles->random_seed;
frame_params.explosiveness = p_particles->explosiveness;
frame_params.randomness = p_particles->randomness;
@ -1158,6 +1158,10 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
//fill the trail params
for (uint32_t i = 0; i < p_particles->trail_params.size(); i++) {
uint32_t src_idx = i * p_particles->frame_history.size() / p_particles->trail_params.size();
if (p_particles->speed_scale <= 0.0) {
// Stop trails.
src_idx = 0;
}
p_particles->trail_params[i] = p_particles->frame_history[src_idx];
}
} else {
@ -1529,7 +1533,6 @@ void ParticlesStorage::update_particles() {
}
}
bool zero_time_scale = Engine::get_singleton()->get_time_scale() <= 0.0;
double todo = particles->request_process_time;
if (particles->clear) {
todo += particles->pre_process_time;
@ -1554,37 +1557,26 @@ void ParticlesStorage::update_particles() {
particles->speed_scale = tmp_scale;
}
double time_scale = MAX(particles->speed_scale, 0.0);
if (fixed_fps > 0) {
double frame_time;
double decr;
if (zero_time_scale) {
frame_time = 0.0;
decr = 1.0 / fixed_fps;
} else {
frame_time = 1.0 / fixed_fps;
decr = frame_time;
}
double frame_time = 1.0 / fixed_fps;
double delta = RendererCompositorRD::get_singleton()->get_frame_delta_time();
if (delta > 0.1) { //avoid recursive stalls if fps goes below 10
delta = 0.1;
} else if (delta <= 0.0) { //unlikely but..
delta = 0.001;
}
todo = particles->frame_remainder + delta;
todo = particles->frame_remainder + delta * time_scale;
while (todo >= frame_time || particles->clear) {
_particles_process(particles, frame_time);
todo -= decr;
todo -= frame_time;
}
particles->frame_remainder = todo;
} else {
if (zero_time_scale) {
_particles_process(particles, 0.0);
} else {
_particles_process(particles, RendererCompositorRD::get_singleton()->get_frame_delta_time());
}
_particles_process(particles, RendererCompositorRD::get_singleton()->get_frame_delta_time() * time_scale);
}
// Ensure that memory is initialized (the code above should ensure that _particles_process is always called at least once upon clearing).