Jump to content

mesh based particle system


jerome
 Share

Recommended Posts

Hi,

 

I'm investigating on the GC with the CPU profiler.

I get rid off the closure that was in th SPS setParticles() code, just in case closures were the cause of the memory allocations. Nothing changed.

 

Here is an very simple example : http://www.babylonjs-playground.com/#2KSQ1R#20

 

As you can see, there is no animation : a SPS is built, then setParticles() is called each frame. Particle positions are just set before to an initial random position with initParticles(). That's all.

 

To exonerate computeNormals() and computeWorldMatrix(), they aren't used in this example, so they can't have effect on the GC. I even tried to get rid off the rotation matrix computation : nothing changed, same GC activity.

 

This looks like something deeper in BJS allocates memory... unless I can't see something obvious in my own code.

 

 

Well, this is not the point of this post.

In the example, if you rotate the cam and carefully look at the cubes, you will notice the z-sort is not correct.

All the cubes are just little parts of a single big mesh. So I don't understand why the z-sort isn't correctly applied/updated here.

 

Any idea ?

 

 

 

[EDIT] : for the computeNormals + GC side, I just ran this old test for minutes on my computer http://jerome.bousquie.fr/BJS/computeNormals/optimized.html

no GC is triggered !

So the problem seems to have another source.

Link to comment
Share on other sites

Hey Jerome,

 

About the z-sorting issue: since you use mesh.hasVertexAlpha = true; in the SolidParticleSystem.buildMesh method, your global mesh is recognized as alpha-blended and thus, no writing in the depth buffer is done. You cannot have semi-transparent objects AND depth writing, sadly.

 

What could be done is sorting all the particles by distance to camera, in the case of semi-transparent particles.

Link to comment
Share on other sites

@Jahow : you were totally right.

Disabling the mesh.hasVertexAlpha gives back a correct z-sort.

 

About sorting all the particles by distance from the camera in this very case only (hasVertexAlpha = true), I don't really understand how it is possible as we have only one mesh here.

Maybe re-sorting the mesh indices array, it is to say reorganize the whole mesh geometry, each frame would do the job, if we assume the first faces (indice triplets in the array) declared will be drawn before the last... not even sure.

And it would be a very expensive extra-pass since particles can have different shapes in the SPS : need to sort things and set them back in the same array with potentially different stride for each particle index. Arrg

 

So, I think I will remove the hasVertexAlpha valued to true by default. Everyone will then set it as he needs, knowing the rule you said : "You cannot have semi-transparent objects AND depth writing, sadly."

 

Maybe, later, I will add, only for this case, the kind of sort you just talked about... but I have no idea how to do it because of the single mesh issue.

Link to comment
Share on other sites

You're right in that it would mean reorder the indices array. Also that would require rebuilding completely the geometry buffers each frame. It is not unrealistic in terms of performance, but may be hard to code, I don't know (I'm not familiar enough with the SPS code).

 

Rewriting the buffers each frame is really not that uncommon. That's what the base BJS particle & sprite systems do after all!

Link to comment
Share on other sites

Ok, I'll probably give a try ... later.

 

The only difficulty is to manage a different stride per particle in the indice array. Well, headache on debug :D

I suppose the distance particle.position/camera.position would be a good criterium to reorder particles... I mean, without taking care about each particle size (because they can different also)

Link to comment
Share on other sites

Hi (again) people,

 

here is a first setParticles() optimization : http://www.babylonjs-playground.com/#2KSQ1R#21

 

The GC has been drastically decreased in the CPU profile on my computer. Only four integer variables (indexes) are now used in this function.

FYI, the best gain was got when deleting a that  (that = this;) variable needed by a closure. The closure itselft had no real effect on the GC, but the that variable usage had one (don't know why).

 

In this example, you've got 200 cubes and 200 torus knots slowly rotating according to their initial random position in space. No normal recomputation each frame and no vertex alpha.

The GC here, in a local example (outside PG) is profiled at 3% max.

 

What I learnt from this : if a function is to be called in the render loop, it is better to avoid the maximum temporary local variables, even scalar values.

If you have to choose between accessing a value through a property this.foo.bar.x many times or store this value once var x = this.foo.bar.x and then to use many times this variable, you should choose the first solution.

Indeed the per property access cost seems lower than the GC variable cleanup cost once the render loop has started.

Link to comment
Share on other sites

Ok, I just found where (I guess) the other temp variable allocations are.

 

In the setParticles() method, I need to call, for each vertex of each rotating particle the Matrix.RotationYawPitchRollToRef() method.

This method calls itself two other methods (toRotationMatrix() and Quaternion.RotationYawPitchRollToRef() ) which both create many temporary variables :

 

https://github.com/BabylonJS/Babylon.js/blob/master/src/Math/babylon.math.ts#L1680

 

https://github.com/BabylonJS/Babylon.js/blob/master/src/Math/babylon.math.ts#L1557

 

Leads :

add a condition to compute the (numerous) vertex rotation matrices only if the particle rotation is different from zero (won't change anything for rotationg particles)

or

reimplement all that stuff :(

Link to comment
Share on other sites

Don't know...

 

It harder than I tought so far (because of the very good ideas from Fenomas and Jahow) and I'm fighting with the JS code.

Not sure I will have the energy to port it to TS then :P ...

Maybe if I really can achieve it (this means : the expected features and the best local optimization), I will feel proud and then will port it.

 

Don't reall know for now

Link to comment
Share on other sites

Hi Jerome!  Good stuff!

 

Why use addTriangles?

 

PS.addPolygons(100, 10, 3);

 

PS.addTriangles(100, 10);

 

Don't these two lines do the same thing?  Just curious.  :)  http://www.babylonjs-playground.com/#2KSQ1R#24

 

------------------

 

Also... hmm...  maybe PS.addPolygons(100, 10, 3, material);    ?   In that demo, where are the particles getting their diffuseColor from?

 

In another demo... http://www.babylonjs-playground.com/#2KSQ1R#25. I tried using the particle .color... a color4:

PS.initParticles = function () {     var fact = 120;     for (var p = 0; p < this.nbParticles; p++) {       this.particles[p].position = new BABYLON.Vector3((Math.random() - 0.5) * fact, (Math.random() - 0.5) * fact, (Math.random() - 0.5) * fact);       this.particles[p].rotation = new BABYLON.Vector3(Math.random(), Math.random(), Math.random());       this.particles[p].color = new BABYLON.Color4(Math.random(), Math.random(), Math.random(), 1);    }   };

That didn't work so well.  :) Thoughts?  (thx)  Maybe use .material instead of .color?  *shrug*  Performance hell?

Link to comment
Share on other sites

Hey Wingy,

 

The explanation about the difference between triangles, quads or any other polygons : http://www.html5gamedevs.com/topic/15154-mesh-based-particle-system/?p=87217

 

[EDIT] moreover a triangle is only one face (triangle) and a quad only two faces whereas a 3 vertex polygon is 3 faces, a 4 vertex polygon is 4 faces, etc. It has a real effect when dealing with thousands of particles.

 

You can set a Color4 to each particle of course, the alpha channel will be taken in account as usual by activating : 

PSP.mesh.hasVertexAlpha = true;

Maybe, I did a bug on color feature when refactoring the lib, I'll check tomorrow. It used to work so far.

Link to comment
Share on other sites

@Wingy : color bug fixed !

 

It was my fault, I set color.x, y, z, w properties (as for Vector4) in the SPS code instead of color.r, g, b, a properties

 

You can have evolving colors if you set them in the updateParticle(particle) function also

 

http://www.babylonjs-playground.com/#2KSQ1R#27

 

black particles slightly getting red

Link to comment
Share on other sites

As it called for every vertex of every solid particles, I just added an internal Quaternion.RotationYawPitchRoll() method : https://github.com/BabylonJSX/SolidParticleSystem/blob/master/solidparticlesystem.js#L401 with no temp local variables

 

In my local tests with the Chrome CPU profiler, the GC decreases now under 1.5 % !

 

Last version pushed to the link of the  PG

 

 

[Edit] added another tiny optimization : the quaternions are now computed only if a mesh or particle rotation if different from zero.

Link to comment
Share on other sites

Some stress tests with Chrome here :

each particle has its own velocity, scale, color and rotation,

measures with debugLayer

 

I put here the limits (rounded to thousands) before it becomes lower than 60 fps

 

plane particles :

 

billboard mode, no normal : 3000 triangles + 1000 quads + 1000 pentagons + 1000 hexagons = 6000 plane particles facing the cam

billboard mode with light reflection : 1500 triangles + 1000 quads + 1000 pentagons + 1000 hexagons = 4500 plane particles facing the cam + reflecting

 

normal mode, no normal : 7000 triangles + 1000 quads + 1000 pentagons + 1000 hexagons = 10 K plane particles

normal mode with light reflection: 2000 triangles + 1000 quads + 1000 pentagons + 1000 hexagons = 5000 plane particles

 

 

3D particles (I don't test the billboard mode here) :

 

no normals : 2500 tetrahedrons + 1000 cubes = 3500 solid particles

with normals : 1500 tetrahedrons + 500 cubes = 2000 solid particles reflecting light

 

If you then use some custom shapes with SPS.addShape(), like cylinders, spheres, torus, ribbons, whatever, the performance is directly related to the amount of vertices and indices to manage.

 

In order to compare, we keep the same particle properties here (own velocity, color, rotation and scale) and we set the SPS in the same "mode" than the BJS particle system or the Fenomas mesh particle system.

It is to say : only quads in billboard mode and no normals.

The SPS here reach 10 K particles.

 

I guess both other system do better in terms of performance.

For plane particles, the SPS is slower but has a better compositing than the BJS internal one and the ability to rotate (mesh and particles), to reflect the light or to mix different shapes which are absent features in one or the other.

Moreover the SPS has no integrated behavior, it is to say no emitter whereas BJS and Fenomas ones provide an emitter. You have to code it by your own here.

 

For solid particles, I'm afraid you don't have the choice so far...

 

have fun : http://www.babylonjs-playground.com/#2KSQ1R#28

Link to comment
Share on other sites

and above all : just one mesh  ;)

 

 

[EDIT] tested at home on my pushcart laptop : runs at 60 fps !

I'm very proud of it because I know I wouldn't have succeeded to make 400 different meshes rotate and orbitate with the classical way on this computer

Link to comment
Share on other sites

So, now, a snow blower?  (mesh blower)  One meter of fresh mesh has fallen on the small Canadian village of Polygonia, Manitoba.  Your job is to build the first mesh blower.  :)

 

7855a05bbad6fec064df4fc4e0202203.jpg

 

errr... maybe not. 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...