2
0
Эх сурвалжийг харах

Fixes to CPU particles for performance and avoiding NaNs.

Juan Linietsky 7 жил өмнө
parent
commit
14494dddd0

+ 32 - 30
drivers/gles3/rasterizer_storage_gles3.cpp

@@ -4066,35 +4066,37 @@ void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances
 
 		multimesh->data.resize(format_floats * p_instances);
 
+		float *dataptr = multimesh->data.ptrw();
+
 		for (int i = 0; i < p_instances * format_floats; i += format_floats) {
 
 			int color_from = 0;
 			int custom_data_from = 0;
 
 			if (multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D) {
-				multimesh->data.write[i + 0] = 1.0;
-				multimesh->data.write[i + 1] = 0.0;
-				multimesh->data.write[i + 2] = 0.0;
-				multimesh->data.write[i + 3] = 0.0;
-				multimesh->data.write[i + 4] = 0.0;
-				multimesh->data.write[i + 5] = 1.0;
-				multimesh->data.write[i + 6] = 0.0;
-				multimesh->data.write[i + 7] = 0.0;
+				dataptr[i + 0] = 1.0;
+				dataptr[i + 1] = 0.0;
+				dataptr[i + 2] = 0.0;
+				dataptr[i + 3] = 0.0;
+				dataptr[i + 4] = 0.0;
+				dataptr[i + 5] = 1.0;
+				dataptr[i + 6] = 0.0;
+				dataptr[i + 7] = 0.0;
 				color_from = 8;
 				custom_data_from = 8;
 			} else {
-				multimesh->data.write[i + 0] = 1.0;
-				multimesh->data.write[i + 1] = 0.0;
-				multimesh->data.write[i + 2] = 0.0;
-				multimesh->data.write[i + 3] = 0.0;
-				multimesh->data.write[i + 4] = 0.0;
-				multimesh->data.write[i + 5] = 1.0;
-				multimesh->data.write[i + 6] = 0.0;
-				multimesh->data.write[i + 7] = 0.0;
-				multimesh->data.write[i + 8] = 0.0;
-				multimesh->data.write[i + 9] = 0.0;
-				multimesh->data.write[i + 10] = 1.0;
-				multimesh->data.write[i + 11] = 0.0;
+				dataptr[i + 0] = 1.0;
+				dataptr[i + 1] = 0.0;
+				dataptr[i + 2] = 0.0;
+				dataptr[i + 3] = 0.0;
+				dataptr[i + 4] = 0.0;
+				dataptr[i + 5] = 1.0;
+				dataptr[i + 6] = 0.0;
+				dataptr[i + 7] = 0.0;
+				dataptr[i + 8] = 0.0;
+				dataptr[i + 9] = 0.0;
+				dataptr[i + 10] = 1.0;
+				dataptr[i + 11] = 0.0;
 				color_from = 12;
 				custom_data_from = 12;
 			}
@@ -4109,14 +4111,14 @@ void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances
 				} cu;
 
 				cu.colu = 0xFFFFFFFF;
-				multimesh->data.write[i + color_from + 0] = cu.colf;
+				dataptr[i + color_from + 0] = cu.colf;
 				custom_data_from = color_from + 1;
 
 			} else if (multimesh->color_format == VS::MULTIMESH_COLOR_FLOAT) {
-				multimesh->data.write[i + color_from + 0] = 1.0;
-				multimesh->data.write[i + color_from + 1] = 1.0;
-				multimesh->data.write[i + color_from + 2] = 1.0;
-				multimesh->data.write[i + color_from + 3] = 1.0;
+				dataptr[i + color_from + 0] = 1.0;
+				dataptr[i + color_from + 1] = 1.0;
+				dataptr[i + color_from + 2] = 1.0;
+				dataptr[i + color_from + 3] = 1.0;
 				custom_data_from = color_from + 4;
 			}
 
@@ -4130,13 +4132,13 @@ void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances
 				} cu;
 
 				cu.colu = 0;
-				multimesh->data.write[i + custom_data_from + 0] = cu.colf;
+				dataptr[i + custom_data_from + 0] = cu.colf;
 
 			} else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) {
-				multimesh->data.write[i + custom_data_from + 0] = 0.0;
-				multimesh->data.write[i + custom_data_from + 1] = 0.0;
-				multimesh->data.write[i + custom_data_from + 2] = 0.0;
-				multimesh->data.write[i + custom_data_from + 3] = 0.0;
+				dataptr[i + custom_data_from + 0] = 0.0;
+				dataptr[i + custom_data_from + 1] = 0.0;
+				dataptr[i + custom_data_from + 2] = 0.0;
+				dataptr[i + custom_data_from + 3] = 0.0;
 			}
 		}
 

+ 17 - 4
scene/3d/cpu_particles.cpp

@@ -592,7 +592,7 @@ void CPUParticles::_particles_process(float p_delta) {
 
 				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));
-				direction_yz.z = direction_yz.z / Math::sqrt(direction_yz.z); //better uniform distribution
+				direction_yz.z = direction_yz.z / MAX(0.0001, Math::sqrt(ABS(direction_yz.z))); //better uniform distribution
 				Vector3 direction = Vector3(direction_xz.x * direction_yz.z, direction_yz.y, direction_xz.z * direction_yz.z);
 				direction.normalize();
 				p.velocity = direction * parameters[PARAM_INITIAL_LINEAR_VELOCITY] * Math::lerp(1.0f, float(Math::randf()), randomness[PARAM_INITIAL_LINEAR_VELOCITY]);
@@ -977,6 +977,8 @@ void CPUParticles::_update_particle_data_buffer() {
 
 			ptr += 17;
 		}
+
+		can_update = true;
 	}
 
 #ifndef NO_THREADS
@@ -989,8 +991,10 @@ void CPUParticles::_update_render_thread() {
 #ifndef NO_THREADS
 	update_mutex->lock();
 #endif
-
-	VS::get_singleton()->multimesh_set_as_bulk_array(multimesh, particle_data);
+	if (can_update) {
+		VS::get_singleton()->multimesh_set_as_bulk_array(multimesh, particle_data);
+		can_update = false; //wait for next time
+	}
 
 #ifndef NO_THREADS
 	update_mutex->unlock();
@@ -1061,6 +1065,8 @@ void CPUParticles::_notification(int p_what) {
 			}
 		}
 
+		bool processed = false;
+
 		if (time == 0 && pre_process_time > 0.0) {
 
 			float frame_time;
@@ -1073,6 +1079,7 @@ void CPUParticles::_notification(int p_what) {
 
 			while (todo >= 0) {
 				_particles_process(frame_time);
+				processed = true;
 				todo -= frame_time;
 			}
 		}
@@ -1091,6 +1098,7 @@ void CPUParticles::_notification(int p_what) {
 
 			while (todo >= frame_time) {
 				_particles_process(frame_time);
+				processed = true;
 				todo -= decr;
 			}
 
@@ -1098,9 +1106,12 @@ void CPUParticles::_notification(int p_what) {
 
 		} else {
 			_particles_process(delta);
+			processed = true;
 		}
 
-		_update_particle_data_buffer();
+		if (processed) {
+			_update_particle_data_buffer();
+		}
 	}
 }
 
@@ -1424,6 +1435,8 @@ CPUParticles::CPUParticles() {
 		flags[i] = false;
 	}
 
+	can_update = false;
+
 	set_color(Color(1, 1, 1, 1));
 
 #ifndef NO_THREADS

+ 2 - 0
scene/3d/cpu_particles.h

@@ -142,6 +142,8 @@ private:
 	int fixed_fps;
 	bool fractional_delta;
 
+	volatile bool can_update;
+
 	DrawOrder draw_order;
 
 	Ref<Mesh> mesh;

+ 1 - 1
scene/resources/particles_material.cpp

@@ -308,7 +308,7 @@ void ParticlesMaterial::_update_shader() {
 		code += "		float angle2_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad * (1.0 - flatness);\n";
 		code += "		vec3 direction_xz = vec3(sin(angle1_rad), 0, cos(angle1_rad));\n";
 		code += "		vec3 direction_yz = vec3(0, sin(angle2_rad), cos(angle2_rad));\n";
-		code += "		direction_yz.z = direction_yz.z / sqrt(direction_yz.z); // better uniform distribution\n";
+		code += "		direction_yz.z = direction_yz.z / max(0.0001,sqrt(abs(direction_yz.z))); // better uniform distribution\n";
 		code += "		vec3 direction = vec3(direction_xz.x * direction_yz.z, direction_yz.y, direction_xz.z * direction_yz.z);\n";
 		code += "		direction = normalize(direction);\n";
 		code += "		VELOCITY = direction * initial_linear_velocity * mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n";