In Godot's Particle System, how can I achieve an effect similar to the Unity particle effect shown in the image below?

Godot Version

Godot4.5.1

Question

In Unity, I just need to set the Render Mode in the Renderer to Stretched Billboard to get this effect. The emitted particles lock to one axis, while the other axis rotates as the camera moves.

In Godot’s Particle System, I can only set Billboard to Y-Billboard in the StandardMaterial3D. It may look similar at first glance, but issues arise when I want the particles to emit along the emitter’s direction. To get the effect in the image, I have to set Billboard to Disabled and then enable align_Y in ParticleProcessMaterial > Particle Flags. This allows the particles to emit along the emitter’s direction, but a new problem occurs: the particles no longer lock to a single axis, and the other axis rotates around the camera instead.

Afaik it’s not doable out of the box but you can write a custom shader that billboards it exactly as you want it.

Yes, you should be able to do it in the visual shader. What is your mesh? A quad in xy plane?

It’s a Quad mesh, and I scale down one of the axes via the XY scaling in the particle system

You scale down x and you align y to the particle velocity? And now you want the quad to rotate along its local y axis to face the camera?

1 Like

Exactly

Here’s the recipe for the vertex function:

  • find the look vector (a direction from the camera to the vertex) in local space - you can do this by transforming the world camera position to object space and then subtracting from the local vertex position.
  • find the vector that is perpendicular to this local look vector and local y axis by taking the cross product of the two and normalizing it, we’ll call this the bitangent vector.
  • move the vertex to the centerline by setting its x to 0 and then move it along the bitangent for the distance of 0.5 (assuming the quad is 1x1)

This should “rotate” the quad along its local y axis so it best faces the camera.

Here’s the shader code. You can use it together with the above description as a reference to build the visual shader

void vertex() {
	vec3 camera_local = (inverse(MODEL_MATRIX) * vec4(CAMERA_POSITION_WORLD, 1.0)).xyz;
	vec3 look_local = camera_local - vec3(0.0, VERTEX.y, 0.0); 
		
	// bitangent in object space
	vec3 bitang_local = normalize(cross(vec3(0.0, 1.0, 0.0), look_local));

	// extrude vertex position from central axis along bitangent
	float direction = sign(VERTEX.x);
	VERTEX.x = 0.0;
	VERTEX += bitang_local * direction * 0.5;
}

2 Likes

3Q,I’ll go give it a try

1 Like