Fixed cpuparticles randomness regression caused by #92089

This commit is contained in:
Qbieshay 2025-01-21 12:00:31 +01:00
parent 1b7b009674
commit c8b0509b7c
4 changed files with 49 additions and 35 deletions

View file

@ -31,6 +31,7 @@
#include "cpu_particles_2d.h"
#include "cpu_particles_2d.compat.inc"
#include "core/math/random_number_generator.h"
#include "scene/2d/gpu_particles_2d.h"
#include "scene/resources/atlas_texture.h"
#include "scene/resources/canvas_item_material.h"
@ -769,22 +770,22 @@ void CPUParticles2D::_particles_process(double p_delta) {
}
p.seed = seed + uint32_t(i) + i + cycle;
uint32_t _seed = p.seed;
rng->set_seed(p.seed);
p.angle_rand = rand_from_seed(_seed);
p.scale_rand = rand_from_seed(_seed);
p.hue_rot_rand = rand_from_seed(_seed);
p.anim_offset_rand = rand_from_seed(_seed);
p.angle_rand = rng->randf();
p.scale_rand = rng->randf();
p.hue_rot_rand = rng->randf();
p.anim_offset_rand = rng->randf();
if (color_initial_ramp.is_valid()) {
p.start_color_rand = color_initial_ramp->get_color_at_offset(rand_from_seed(_seed));
p.start_color_rand = color_initial_ramp->get_color_at_offset(rng->randf());
} else {
p.start_color_rand = Color(1, 1, 1, 1);
}
real_t angle1_rad = direction.angle() + Math::deg_to_rad((rand_from_seed(_seed) * 2.0 - 1.0) * spread);
real_t angle1_rad = direction.angle() + Math::deg_to_rad((rng->randf() * 2.0 - 1.0) * spread);
Vector2 rot = Vector2(Math::cos(angle1_rad), Math::sin(angle1_rad));
p.velocity = rot * Math::lerp(parameters_min[PARAM_INITIAL_LINEAR_VELOCITY], parameters_max[PARAM_INITIAL_LINEAR_VELOCITY], (real_t)rand_from_seed(_seed));
p.velocity = rot * Math::lerp(parameters_min[PARAM_INITIAL_LINEAR_VELOCITY], parameters_max[PARAM_INITIAL_LINEAR_VELOCITY], rng->randf());
real_t base_angle = tex_angle * Math::lerp(parameters_min[PARAM_ANGLE], parameters_max[PARAM_ANGLE], p.angle_rand);
p.rotation = Math::deg_to_rad(base_angle);
@ -792,7 +793,7 @@ void CPUParticles2D::_particles_process(double p_delta) {
p.custom[0] = 0.0; // unused
p.custom[1] = 0.0; // phase [0..1]
p.custom[2] = tex_anim_offset * Math::lerp(parameters_min[PARAM_ANIM_OFFSET], parameters_max[PARAM_ANIM_OFFSET], p.anim_offset_rand);
p.custom[3] = (1.0 - rand_from_seed(_seed) * lifetime_randomness);
p.custom[3] = (1.0 - rng->randf() * lifetime_randomness);
p.transform = Transform2D();
p.time = 0;
p.lifetime = lifetime * p.custom[3];
@ -803,17 +804,17 @@ void CPUParticles2D::_particles_process(double p_delta) {
//do none
} break;
case EMISSION_SHAPE_SPHERE: {
real_t t = Math_TAU * rand_from_seed(_seed);
real_t radius = emission_sphere_radius * rand_from_seed(_seed);
real_t t = Math_TAU * rng->randf();
real_t radius = emission_sphere_radius * rng->randf();
p.transform[2] = Vector2(Math::cos(t), Math::sin(t)) * radius;
} break;
case EMISSION_SHAPE_SPHERE_SURFACE: {
real_t s = rand_from_seed(_seed), t = Math_TAU * rand_from_seed(_seed);
real_t s = rng->randf(), t = Math_TAU * rng->randf();
real_t radius = emission_sphere_radius * Math::sqrt(1.0 - s * s);
p.transform[2] = Vector2(Math::cos(t), Math::sin(t)) * radius;
} break;
case EMISSION_SHAPE_RECTANGLE: {
p.transform[2] = Vector2(rand_from_seed(_seed) * 2.0 - 1.0, rand_from_seed(_seed) * 2.0 - 1.0) * emission_rect_extents;
p.transform[2] = Vector2(rng->randf() * 2.0 - 1.0, rng->randf() * 2.0 - 1.0) * emission_rect_extents;
} break;
case EMISSION_SHAPE_POINTS:
case EMISSION_SHAPE_DIRECTED_POINTS: {
@ -1523,6 +1524,8 @@ CPUParticles2D::CPUParticles2D() {
set_amount(8);
set_use_local_coordinates(false);
rng.instantiate();
set_param_min(PARAM_INITIAL_LINEAR_VELOCITY, 0);
set_param_min(PARAM_ANGULAR_VELOCITY, 0);
set_param_min(PARAM_ORBIT_VELOCITY, 0);

View file

@ -33,6 +33,8 @@
#include "scene/2d/node_2d.h"
class RandomNumberGenerator;
class CPUParticles2D : public Node2D {
private:
GDCLASS(CPUParticles2D, Node2D);
@ -179,6 +181,8 @@ private:
Vector2 gravity = Vector2(0, 980);
Ref<RandomNumberGenerator> rng;
void _update_internal();
void _particles_process(double p_delta);
void _update_particle_data_buffer();

View file

@ -31,6 +31,7 @@
#include "cpu_particles_3d.h"
#include "cpu_particles_3d.compat.inc"
#include "core/math/random_number_generator.h"
#include "scene/3d/camera_3d.h"
#include "scene/3d/gpu_particles_3d.h"
#include "scene/main/viewport.h"
@ -818,27 +819,27 @@ void CPUParticles3D::_particles_process(double p_delta) {
tex_anim_offset = curve_parameters[PARAM_ANGLE]->sample(tv);
}
p.seed = seed;
uint32_t _seed = seed + uint32_t(1) + i + cycle;
p.angle_rand = rand_from_seed(_seed);
p.scale_rand = rand_from_seed(_seed);
p.hue_rot_rand = rand_from_seed(_seed);
p.anim_offset_rand = rand_from_seed(_seed);
p.seed = seed + uint32_t(1) + i + cycle;
rng->set_seed(p.seed);
p.angle_rand = rng->randf();
p.scale_rand = rng->randf();
p.hue_rot_rand = rng->randf();
p.anim_offset_rand = rng->randf();
if (color_initial_ramp.is_valid()) {
p.start_color_rand = color_initial_ramp->get_color_at_offset(rand_from_seed(_seed));
p.start_color_rand = color_initial_ramp->get_color_at_offset(rng->randf());
} else {
p.start_color_rand = Color(1, 1, 1, 1);
}
if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
real_t angle1_rad = Math::atan2(direction.y, direction.x) + Math::deg_to_rad((rand_from_seed(_seed) * 2.0 - 1.0) * spread);
real_t angle1_rad = Math::atan2(direction.y, direction.x) + Math::deg_to_rad((rng->randf() * 2.0 - 1.0) * spread);
Vector3 rot = Vector3(Math::cos(angle1_rad), Math::sin(angle1_rad), 0.0);
p.velocity = rot * Math::lerp(parameters_min[PARAM_INITIAL_LINEAR_VELOCITY], parameters_max[PARAM_INITIAL_LINEAR_VELOCITY], rand_from_seed(_seed));
p.velocity = rot * Math::lerp(parameters_min[PARAM_INITIAL_LINEAR_VELOCITY], parameters_max[PARAM_INITIAL_LINEAR_VELOCITY], rng->randf());
} else {
//initiate velocity spread in 3D
real_t angle1_rad = Math::deg_to_rad((rand_from_seed(_seed) * (real_t)2.0 - (real_t)1.0) * spread);
real_t angle2_rad = Math::deg_to_rad((rand_from_seed(_seed) * (real_t)2.0 - (real_t)1.0) * ((real_t)1.0 - flatness) * spread);
real_t angle1_rad = Math::deg_to_rad((rng->randf() * (real_t)2.0 - (real_t)1.0) * spread);
real_t angle2_rad = Math::deg_to_rad((rng->randf() * (real_t)2.0 - (real_t)1.0) * ((real_t)1.0 - flatness) * spread);
Vector3 direction_xz = Vector3(Math::sin(angle1_rad), 0, Math::cos(angle1_rad));
Vector3 direction_yz = Vector3(0, Math::sin(angle2_rad), Math::cos(angle2_rad));
@ -858,14 +859,14 @@ void CPUParticles3D::_particles_process(double p_delta) {
binormal.normalize();
Vector3 normal = binormal.cross(direction_nrm);
spread_direction = binormal * spread_direction.x + normal * spread_direction.y + direction_nrm * spread_direction.z;
p.velocity = spread_direction * Math::lerp(parameters_min[PARAM_INITIAL_LINEAR_VELOCITY], parameters_max[PARAM_INITIAL_LINEAR_VELOCITY], rand_from_seed(_seed));
p.velocity = spread_direction * Math::lerp(parameters_min[PARAM_INITIAL_LINEAR_VELOCITY], parameters_max[PARAM_INITIAL_LINEAR_VELOCITY], rng->randf());
}
real_t base_angle = tex_angle * Math::lerp(parameters_min[PARAM_ANGLE], parameters_max[PARAM_ANGLE], p.angle_rand);
p.custom[0] = Math::deg_to_rad(base_angle); //angle
p.custom[1] = 0.0; //phase
p.custom[2] = tex_anim_offset * Math::lerp(parameters_min[PARAM_ANIM_OFFSET], parameters_max[PARAM_ANIM_OFFSET], p.anim_offset_rand); //animation offset (0-1)
p.custom[3] = (1.0 - rand_from_seed(_seed) * lifetime_randomness);
p.custom[3] = (1.0 - rng->randf() * lifetime_randomness);
p.transform = Transform3D();
p.time = 0;
p.lifetime = lifetime * p.custom[3];
@ -876,20 +877,20 @@ void CPUParticles3D::_particles_process(double p_delta) {
//do none
} break;
case EMISSION_SHAPE_SPHERE: {
real_t s = 2.0 * rand_from_seed(_seed) - 1.0;
real_t t = Math_TAU * rand_from_seed(_seed);
real_t x = rand_from_seed(_seed);
real_t s = 2.0 * rng->randf() - 1.0;
real_t t = Math_TAU * rng->randf();
real_t x = rng->randf();
real_t radius = emission_sphere_radius * Math::sqrt(1.0 - s * s);
p.transform.origin = Vector3(0, 0, 0).lerp(Vector3(radius * Math::cos(t), radius * Math::sin(t), emission_sphere_radius * s), x);
} break;
case EMISSION_SHAPE_SPHERE_SURFACE: {
real_t s = 2.0 * rand_from_seed(_seed) - 1.0;
real_t t = Math_TAU * rand_from_seed(_seed);
real_t s = 2.0 * rng->randf() - 1.0;
real_t t = Math_TAU * rng->randf();
real_t radius = emission_sphere_radius * Math::sqrt(1.0 - s * s);
p.transform.origin = Vector3(radius * Math::cos(t), radius * Math::sin(t), emission_sphere_radius * s);
} break;
case EMISSION_SHAPE_BOX: {
p.transform.origin = Vector3(rand_from_seed(_seed) * 2.0 - 1.0, rand_from_seed(_seed) * 2.0 - 1.0, rand_from_seed(_seed) * 2.0 - 1.0) * emission_box_extents;
p.transform.origin = Vector3(rng->randf() * 2.0 - 1.0, rng->randf() * 2.0 - 1.0, rng->randf() * 2.0 - 1.0) * emission_box_extents;
} break;
case EMISSION_SHAPE_POINTS:
case EMISSION_SHAPE_DIRECTED_POINTS: {
@ -933,11 +934,11 @@ void CPUParticles3D::_particles_process(double p_delta) {
case EMISSION_SHAPE_RING: {
real_t radius_clamped = MAX(0.001, emission_ring_radius);
real_t top_radius = MAX(radius_clamped - Math::tan(Math::deg_to_rad(90.0 - emission_ring_cone_angle)) * emission_ring_height, 0.0);
real_t y_pos = rand_from_seed(_seed);
real_t y_pos = rng->randf();
real_t skew = MAX(MIN(radius_clamped, top_radius) / MAX(radius_clamped, top_radius), 0.5);
y_pos = radius_clamped < top_radius ? Math::pow(y_pos, skew) : 1.0 - Math::pow(y_pos, skew);
real_t ring_random_angle = rand_from_seed(_seed) * Math_TAU;
real_t ring_random_radius = Math::sqrt(rand_from_seed(_seed) * (radius_clamped * radius_clamped - emission_ring_inner_radius * emission_ring_inner_radius) + emission_ring_inner_radius * emission_ring_inner_radius);
real_t ring_random_angle = rng->randf() * Math_TAU;
real_t ring_random_radius = Math::sqrt(rng->randf() * (radius_clamped * radius_clamped - emission_ring_inner_radius * emission_ring_inner_radius) + emission_ring_inner_radius * emission_ring_inner_radius);
ring_random_radius = Math::lerp(ring_random_radius, ring_random_radius * (top_radius / radius_clamped), y_pos);
Vector3 axis = emission_ring_axis == Vector3(0.0, 0.0, 0.0) ? Vector3(0.0, 0.0, 1.0) : emission_ring_axis.normalized();
Vector3 ortho_axis;
@ -1764,6 +1765,8 @@ CPUParticles3D::CPUParticles3D() {
set_emitting(true);
set_amount(8);
rng.instantiate();
set_param_min(PARAM_INITIAL_LINEAR_VELOCITY, 0);
set_param_min(PARAM_ANGULAR_VELOCITY, 0);
set_param_min(PARAM_ORBIT_VELOCITY, 0);

View file

@ -33,6 +33,8 @@
#include "scene/3d/visual_instance_3d.h"
class RandomNumberGenerator;
class CPUParticles3D : public GeometryInstance3D {
private:
GDCLASS(CPUParticles3D, GeometryInstance3D);
@ -190,6 +192,8 @@ private:
Vector3 gravity = Vector3(0, -9.8, 0);
Ref<RandomNumberGenerator> rng;
void _update_internal();
void _particles_process(double p_delta);
void _update_particle_data_buffer();