Godot: [TRACKER] Inconsistencies between GPU Particles(2D) and CPUParticles(2D)

Created on 11 Jun 2019  路  9Comments  路  Source: godotengine/godot

Godot version:
3.2 master (15425b45)

OS/device including version:
Any OS, GLES3

Issue description:

While testing conversions from Particles2D to CPUParticles2D, I noticed a few things which do not get properly converted or do not work the same way once converted in the CPU variant. Similar issues exist for Particles -> CPUParticles (3D), so it's worth reviewing all 4 nodes systematically to fix or document inconsistencies.

  • [x] Orbital velocity is not exposed in CPUParticles2D and CPUParticles, nor the related FLAG_DISABLE_Z flag. PR #29683

Peek 2019-06-12 12-27
(CPU -- GPU)

  • [x] Tangential acceleration behaves differently (much stronger) in CPUParticles2D compared to Particles2D. The 3D counterpart is also affected if the "Disable Z" flag is enabled. PR #29685

Peek 2019-06-12 12-32
(GPU -- CPU)

  • [x] Time/Emission randomness behaves differently in CPUParticles2D and CPUParticles, with almost no visible effect. There is something fishy in the way lifetime is used or missing as a factor in the randomness code, and a fix similar to c13ac398f might be needed. PR #29696

Peek 2019-06-12 12-37
(CPU -- GPU)

  • [ ] Trail properties are not implemented in CPUParticles2D and CPUParticles. It's not clear yet whether this is by design (technical limitation) or omission.

Peek 2019-06-12 12-23
(GPU -- CPU)

  • [x] CPUParticles2D's "Sphere" emission shape is actually a circle (outline only), while Particles2D's is a disc ("filled circle"), or might even actually be a sphere projected on a 2D plane (it kind of feels like the emission density is higher on the edges than in the center, giving an impression of spherical surface). PR #29854

Peek 2019-06-12 12-25
(CPU -- GPU)

Will add more as I find them.

Test project: particles.zip
Note: The "Direction_Mask" Particles2D in the original demo, and kept in this example, seems to be kind of broken, as it will work some times and fail at other times. Disabling the "Disable Z" flag on the Particles2D seem to make it work more reliably, but I suspect some uninitialized variable or other issue.

bug 3.2 core tracker

Most helpful comment

@akien-mga The Particles2D sphere is actually just a projected 3D sphere (so you're correct about that). In a way, it makes sense as the UI says under "Flags": "Disable Z" and if you had to "disable Z" you would of course use orthogonal projection.

The CPUParticles2D sphere is a non-uniform density circle as it is created by normalizing uniformly distributed random points in a square. This means that the "diagonal regions" have a point density of sqrt(2) times that of the "cardinal regions". That can be fixed by using trigonometric functions at the cost of some performance
(i.e. t = 2 * PI * Math::randf(); x = r * cos(t); y = r * sin(t);).

Of course, it is not up to me to decide what is important to you (or anyone else), so take this more as a description of the status quo than a recommendation.

All 9 comments

I made a test project for Particles2D & CPUParticles2D based on the 2d/particles official demo:
particles.zip

In the cpuparticles.tscn scene, all particle effects have been duplicated the duplicate converted to CPUParticles2D using the editor plugin feature. It illustrates some of the bugs outside above and some more, especially when you start playing with the various directional acceleration properties which often do nothing for CPUParticles2D.

I have found a couple while working on https://github.com/godotengine/godot/pull/29700

These are 3D

  • [x] Depth draw order lifetime reversed for CPUParticles (same as https://github.com/godotengine/godot/issues/29440) (Will be addressed in #29700)

  • [x] Depth draw order view_depth doesn't match Particles (will be addressed in #29700)

  • [x] Default velocity is 1 in CPUParticles while it is 0 in Particles (Junior Job: just change 1 to 0 here) PR #29958

A few from the test case (2D):

  • [ ] Emission mask not maintained when converting to CPUParticles2D

  • [ ] Visibility rect not drawn in CPUParticles2D (start by copying from here https://github.com/godotengine/godot/blob/f410e7a8a9b14fd9f5c210afcc9e3519e9ce246d/scene/2d/particles_2d.cpp#L297-L300) )

Visibility rect not drawn in CPUParticles2D (start by copying from here)

Regarding the visibility rect, @JFonS told me that the property was not added to CPUParticles* as it's computed automatically. But maybe we still want to draw the computed rect?

Edit: Actually, CPUParticles also doesn't have its visibility AABB drawn and it can't be selected.

@akien-mga The Particles2D sphere is actually just a projected 3D sphere (so you're correct about that). In a way, it makes sense as the UI says under "Flags": "Disable Z" and if you had to "disable Z" you would of course use orthogonal projection.

The CPUParticles2D sphere is a non-uniform density circle as it is created by normalizing uniformly distributed random points in a square. This means that the "diagonal regions" have a point density of sqrt(2) times that of the "cardinal regions". That can be fixed by using trigonometric functions at the cost of some performance
(i.e. t = 2 * PI * Math::randf(); x = r * cos(t); y = r * sin(t);).

Of course, it is not up to me to decide what is important to you (or anyone else), so take this more as a description of the status quo than a recommendation.

Would prefer a uniform distribution in a circle, like @simonpuchert supplied an algorithm for :+1:

Would prefer a uniform distribution in a circle, like @simonpuchert supplied an algorithm for 馃憤

That code creates a circle outline, we have decided to go with the sphere for CPUParticles2D to match the behaviour of Particles2D. We have discussed adding a circle option and a square option later. But for now, it makes the most sense for the two types of particles to have the same behaviour.

But for now, it makes the most sense for the two types of particles to have the same behaviour.

Sorry about that, what i meant that it would be nice to have uniform circle distribution of particles, for both particles2d and cpuparticles2d! It would also be nice to have the old circle outline and this sphere as options also. Maybe also rect outline? I think several options here is a good thing, since particles need to be unique and highly customizable :) I could open a new issue with feature request?

If you want a similar "algorithm" for the projected sphere, it would be

s = Math::randf();
t = 2*PI*Math::randf();
rad = r*sqrt(1-s^2);
x = rad*cos(t); y = rad*sin(t);

and a 3D sphere would be

s = Math::randf();
t = 2*PI*Math::randf();
rad = r*sqrt(1-s^2);
x = rad*cos(t); y = rad*sin(t); z = r*s;

An easy way to understand how it works is to look at the Lambert equal-area cylindrical projection.

Again, I'm not here to say what you should do, but if you want a uniform distribution on a sphere this is one way to accomplish it.
By the way, scene/3d/cpu_particles.cpp also uses the "normalized cube" method, so it produces the same non-uniform-density sphere.

It might also make sense to track this one #40807 here, because the behavior is different in GPU particles.

Was this page helpful?
0 / 5 - 0 ratings