Jump to content

SPS on the go !


Recommended Posts

These suffer from the same depth-rendering/alpha issues as the standard particles, correct?  From a single SPS, the particles cannot be BEHIND something and also in-front-of something, right?  errr.


If you place a spacecraft in the center of that asteroid field, all the particles will render BEHIND it or IN-FRONT-OF it (afore it?)... but they can't be both?



It's a real mesh, so the same depth-rendering and alpha blending than any other mesh !

That's the initial reason why I started to code this particle system, what became then a solid particle system (why keep things planar when you can have them in 3D ? ;) )


In other terms : your spaceship will have asteroids behind and in front of it, but also on its left, its right, its top and bottom, everywhere around  :P 

Link to comment
Share on other sites

doc updated : https://github.com/BabylonJS/Documentation/blob/master/content/tutorials/03_Advanced/Solid_Particle_System.md


I still need to write the part about textures and colors, and to add tonz of PG examples, then it will be over.

I wish a native english speaker (or a native globish speaker, if he exists) can edit and correct directly this doc then.

Let me know please if something is not understandable.


When the last pending code PR about visibility helpers is merged, I guess the first core full version of the SPS is now released :)

Link to comment
Share on other sites

Hi gals & guys,


Fed up with writing SPS docs (big effort for me to write in english), so I'm starting to code some PG ..


Remember that our SPS, when set as immutable is the same than the ThreeJS BufferGeometry. So let's redo what they did

Here's their big example online : http://threejs.org/examples/webgl_buffergeometry.html

They did 160 000 triangles, using a Phong Material to diffuse the light, in one big mesh, so one draw call only... read the code if you want.


Here's the same with an immutable SPS in BJS : http://www.babylonjs-playground.com/#2FPT1A#5

The code is quite shorter ;) (actually it's in the core).

I did 160 000 double-sided triangles also without any material, one draw call also. The mesh isn't updatable, so VBO update under the hood.

Runs at FPS in my FF which is far more slower than Chrome for WebGL things on my computer (FF uses only one JS engine for all the browser tabs, since Chrome or Edge use a engine thread per tab).


If you want to stress the model, change the var "nb" at the line 16


Note that the PG environment itself, which is also a JS program, can have performance impacts on the demo you are running, compared to the same demo ran alone, outside the PG. The window size has also an impact on the FPS : the bigger, the slower.


Well, knowing all this, let's go for serious things : Chrome (linux guy) + 500 000 particles... yes, half a million

=> 47 FPS if I look at the whole mesh and 60 FPS as soon as I zoom into the mesh

not that bad :P

Link to comment
Share on other sites

Let's go on ...

Now, I turn my SPS from immutable to updatable and I remove the positionFunction parameter in the addShape() call.


I keep myPositionFunction with no change, but I call it in SPS.initParticles() now at the line 41.

Then I call initParticles() and just once setParticles() before the render loop.


So I created an updatable SPS instead of an immutable one : http://www.babylonjs-playground.com/#2FPT1A#7

Same perfs as long as I don't do anything in the render loop.


Ok, now I reduce the SPS to 20K particles because I'm starting to call setParticles() within the render loop.

I set some optimizers to skip some processes while computing everything and I call now setParticles() from the render loop also : http://www.babylonjs-playground.com/#2FPT1A#8

What for to put setParticles() in the render loop ?

Maybe to animate your particles ... just add a SPS.updateParticle(particle) function and give them a behavior : line 47 => rotation


Link to comment
Share on other sites

Very cool! Good job. I am sure there are alot of opportunities to use the SPS in the future, so powerful and versatile.


By the way: Can you make those particles flee from the cursor? Like the birds in this demo: http://threejs.org/examples/canvas_geometry_birds.html (they use some weird math that I don't really understand, but maybe you can :P )

Link to comment
Share on other sites

Very cool! Good job. I am sure there are alot of opportunities to use the SPS in the future, so powerful and versatile.


By the way: Can you make those particles flee from the cursor? Like the birds in this demo: http://threejs.org/examples/canvas_geometry_birds.html (they use some weird math that I don't really understand, but maybe you can :P )


If you want to learn more about flocking behavior this source code is commented:



and this page explains the rules of flocking:


Link to comment
Share on other sites

Let's on go ... today : pickable particles !


Now, I make little tetrahedrons instead of triangles.

My SPS is not immutable and I don't call setParticles() in the render loop : http://www.babylonjs-playground.com/#2FPT1A#11


Something quite classical until now (I like to write "classical" about something that is hardly released :P ), ok ?


Now let's make the SPS pickable at the line 34 :

var SPS = new BABYLON.SolidParticleSystem('SPS', scene, {isPickable: true});

After the first call to setParticles(), let's call refreshVisibleSize() at the line 49 :

SPS.refreshVisibleSize(); // updates the BBox for pickability

the reason why is explained here : http://doc.babylonjs.com/overviews/Solid_Particle_System#pickable-particles


At last, let's add a callback function onPointerDown at the line 55 :

   scene.onPointerDown = function(evt, pickResult) {    var faceId = pickResult.faceId;    if (faceId == -1) {return;}    var idx = SPS.pickedParticles[faceId].idx;    var p = SPS.particles[idx];    p.color.r = 1;    p.color.b = 0;    p.color.g = 0;    p.scale.x = 5;    p.scale.y = 5;    p.scale.z = 5;    SPS.setParticles();  };

faceId is the SPS mesh picked face ID, this is just a BJS feature about pickable meshes.

If nothing picked (-1) then return.

Else, you get in the SPS.pickedParticles array, at the position faceId,  an object telling you which particle was picked (its particle idx) and what face of this particle was picked (its particle faceId).

This objet is like this : { idx: pickedParticleIdx, faceID: pickedParticleFaceID }


So to get the particle from the SPS.particles array, just do this :

    var idx = SPS.pickedParticles[faceId].idx;    var p = SPS.particles[idx];

So in this code, we get the picked particle, we turn it to red, we scale it of 5 and we call setParticles() then to update the SPS mesh.


click any particle :



Quite easy, isn't it ?

Link to comment
Share on other sites

What if now I want to give a behavior to my picked particles ?


Well, always simple ...

Just add SPS.setParticles() in the render loop, no need to call it any longer in onPointerDown then.

Mark the picked particle as picked at the line 66, this is a custom property that you add to the particle object : p.picked = true;

And add an updateParticle(particle) function to your SPS at the line 69

   SPS.updateParticle = function (particle) {       if (particle.picked) {           particle.rotation.x += 0.01;           particle.rotation.y += 0.02;           particle.rotation.z += 0.01;       }   }

That's all : http://www.babylonjs-playground.com/#2FPT1A#13


If 20K particles are too much for your browser, try this lowered version with only 2000 objects : http://www.babylonjs-playground.com/#2FPT1A#14

or with 200 here : http://www.babylonjs-playground.com/#2FPT1A#15

Link to comment
Share on other sites

Based on the article linked in this Adam's post : http://www.html5gamedevs.com/topic/17886-sps-on-the-go/?p=104380

I tried to make a first attempt of flocking here : http://www.babylonjs-playground.com/#2FPT1A#34


The article algo was like this for n particles :

- 3 * n² iterations each pass

- some local temp var created each iteration

- (I guess) a call per frame, so 3 * n² iterations each frame


I changed it a bit :

- only four variables reused : GC friendly

- a call each delay milliseconds : the flocking physics is decoupled now from the render loop

pool * n iterations each call only : pool is a variable that you set yourselft, it's the number of particles to compute each call, it can obviously be equal to n


Note that the flocking process needs to evaluate all the particle positions and velocities at once, so if you set a pool value too low, it will take a long time before the particles start to flock together. So it's better, from my experience, not to have pool lower then n / 3.


The same for delay. Having a short delay (near the framerate) is not necessary.

But having a too long delay may, especially if pool is different from n, makes the particle  be slow to be aware of the positions of their neighbors.


So a delay of 300 ms is still acceptable for pool == n for instance, but you will probably have to reduce it to 150 or 100 ms if pool is n / 2 or  /3

Quite complex to tweak accurately as the total number of particles n has a big impact on the performance too.


I still need to add some particle rotation so they will be orientated to their velocity vector

Link to comment
Share on other sites

Hey Jerome...  nice coding/art, as always!


Ok, if I may steer the subject back to PICKING... have you thought about how ActionManager(s) might be involved in SPS?


Sprites recently got a 'pickable' feature,. and they were given a special sprite helper func in the ActionManager.  (CreateNewFromSprite)  (new Action from a sprite pick).


There is also a (new?) spriteManager intersect function that seems to build a fully stocked pickingInfo in the line 105 area.


All in all, it LOOKS like sprites are actionManager-ready, but I have no idea where we would put the ActionManager.  (on Scene or on the SpriteManager?)


Have you thought about ActionManagers with SPS?  I'm quite sure that the user could put an actionManager on each SPS particle mesh, but that might be insane.


IF actionManagers for SPRITES... is placed on SpriteManager objects... then this is the first time we have seen ActionManagers put on SYSTEMS (managers) and not on a mesh.  (although scene.actionManager is placed on a non-mesh, too.)  


Where ActionManagers are placed... might not be very important.  The main thing is feeding them, I suppose.


Do you foresee ParticleSystem and SolidParticleSystem allowing an actionManager on the SYSTEM (on the manager)?


And, if you do decide to figure a way to add a single, centralized ActionManager in SPS... will you be pondering a similar system for standard particles?  Do you think Standard Particles will follow the way of Sprites (because of the dynamic vertex buffers of both)? 


Would a (single centralized) SPS ActionManager feature be substantially different from sprites and standard particles?


You don't have answer any of that.  I guess I'm just asking for your thoughts on SPS ActionManagers and have you thought about generating ActionEvent.CreateNewFromParticle() for SPS... similar to the way sprite picks do?  Any thoughts?  (thx)


PS:  Has anyone tortured the new array.filter thing?  Is it fast?  Can it be used in customUpdate funcs to... you know... do stuff to CERTAIN particles and not to others?  Tags system on steroids?  hmm.  Iterating the particles array FAST... is probably important in custom particle update funcs.  Just curious if we got some speed increase with array.filter (vs. for-in/for-each).

Link to comment
Share on other sites

Good question


I don't anything about ActionManagers actually. I need to check how this works, what it is intended for, etc  :)


In the SPS, you can give a behavior depending on each particle if you want as updateParticle(particle) is call for each particle and you can then access some internal particle properties : idx (id), shapeId (its shape id), of course some essential properties (position, velocity, color, uvs) and even the hypothetical properties you would have added by your own (age, class, whatever ...)

Link to comment
Share on other sites

I just took a quick look at array.filter

Whatever its speed, I would use it neither in the render loop, neither in a particle system iteration because it creates a new array each call.

Allocating new objects is really a problem when dealing with big sizes (many particles), numerous calls (iterations on a particle array) or with the render loop.


Trust me from my numerous tests and profiling for the SPS : the GC is no longer your friend when it has to clean everything you've just created by hundreds of thousands.

In other terms : you need to balance each function speed performance by its memory performance.


BTW, I guess I need to have a talk with DK about this, because I noticed that there are many places in the core where we can get some gain (reducing the use of temporary variables in many math or vector tools : performance vs readibility). Nothing perceptible on a single per frame, but with a real effect on thousands of calls per frame.


BTW2 : I guess the SPS, first version, is now finished. I still need to complete the (long) documentation and code some more examples, then I'll do an announcement, with trumpets and flags of course  :P

Link to comment
Share on other sites

nod.  Yeah, the more I think about it, the more it seems that the actions available on ActionManagers... are not appropriate for SPS (other than the ExecuteCodeAction).  Forget I mentioned it.  :)  And yes, I'm sure an actionManager on each SPS particle would work just fine, if ever wanted.

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.

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.


  • Recently Browsing   0 members

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