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

Fix GPUParticles2D emission offset in global coords

floppyhammer 3 жил өмнө
parent
commit
0d5472dd1a

+ 15 - 0
servers/rendering/renderer_rd/renderer_storage_rd.cpp

@@ -5712,6 +5712,21 @@ void RendererStorageRD::update_particles() {
 				total_amount *= particles->trail_bind_poses.size();
 			}
 
+			// Affect 2D only.
+			if (particles->use_local_coords) {
+				// In local mode, particle positions are calculated locally (relative to the node position)
+				// and they're also drawn locally.
+				// It works as expected, so we just pass an identity transform.
+				store_transform(Transform3D(), copy_push_constant.inv_emission_transform);
+			} else {
+				// In global mode, particle positions are calculated globally (relative to the canvas origin)
+				// but they're drawn locally.
+				// So, we need to pass the inverse of the emission transform to bring the
+				// particles to local coordinates before drawing.
+				Transform3D inv = particles->emission_transform.affine_inverse();
+				store_transform(inv, copy_push_constant.inv_emission_transform);
+			}
+
 			copy_push_constant.total_particles = total_amount;
 			copy_push_constant.frame_remainder = particles->interpolate ? particles->frame_remainder : 0.0;
 			copy_push_constant.align_mode = particles->transform_align;

+ 2 - 0
servers/rendering/renderer_rd/renderer_storage_rd.h

@@ -852,6 +852,8 @@ private:
 			uint32_t lifetime_split;
 			uint32_t lifetime_reverse;
 			uint32_t copy_mode_2d;
+
+			float inv_emission_transform[16];
 		};
 
 		enum {

+ 8 - 0
servers/rendering/renderer_rd/shaders/particles_copy.glsl

@@ -61,6 +61,8 @@ layout(push_constant, std430) uniform Params {
 	uint lifetime_split;
 	bool lifetime_reverse;
 	bool copy_mode_2d;
+
+	mat4 inv_emission_transform;
 }
 params;
 
@@ -199,6 +201,12 @@ void main() {
 			txform = txform * trail_bind_poses.data[part_ofs];
 		}
 
+		if (params.copy_mode_2d) {
+			// In global mode, bring 2D particles to local coordinates
+			// as they will be drawn with the node position as origin.
+			txform = params.inv_emission_transform * txform;
+		}
+
 		txform = transpose(txform);
 	} else {
 		txform = mat4(vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0)); //zero scale, becomes invisible