General Particle System

Skaldarnar

Badges badges badges badges mushroom mushroom!
Contributor
Art
World
SpecOps
This thread should start some initial discussion and tinkering about generalized particle systems for various occasions. Currently, the only particle system is BlockParticleSystem which is restricted in several ways.

The ultimate goal is to have a set of basic particle systems that can easily be incorporated into modules. Some useful pre-defined effect classes would be for explosion, smoke, fog, ... Moreover, the location where particles should be spawned has to be adjustable, e.g., on the surface of a sphere, inside a cube, ...

Here are the main questions/aspects:
  • where are particles created (relative to some position, defined by position, radius, ...),
  • how many particles and with which rate are spawned,
  • how do they look (form, texture, size, ...)
  • lifetime of particles
  • bounding box in which particles live - any particle leaving this area will be deleted.
For instance, a simple prefab for particles (default, probably smoke) on the outer surface of a sphere could look like follows:
Code:
{
  "SphereParticleEffect" : {
    "radius": 5,
    "surfaceOnly": true
  }
}
Defining an explosion would be as simple:
Code:
{
  "ExplosionParticleEffect" : {
    "radius": 20,
    "acceleration": [300, 300, 300]
   }
}
Another point are repeatedly created particles. Currently one needs to define a separate system which resets the amount of particles to spawn. Probably this could be generalized in class of RepeatableParticleEffect or by using a flag which indicates whether the effect is one-time or not.
 

manu3d

Active Member
Contributor
Architecture
Oh boy. I should be able to say a thing or two about this... :sneaky:

First of all, generally speaking particles should have three sets of interacting components:

1) emitters
2) particles
3) fields

Emitters define things such as initial attributes, i.e. initial location of the particles (a point? a line? an area? a volume? a mesh?) , velocity, size and emission rate. Ideally any of these characteristics should be capable of varying in time, i.e. with animation curves or simple scripts, so that something like the emission rate can be made to ramp up and down as necessary. Also, especially in the context of area/mesh emitters (and to some degrees linear and volume emitters) it is useful to modulate things such as emission rate with a texture, so that some parts of the area emit more and some parts emit less. A texture attached to an area emitter might also define the initial color of the particles, with some areas emitting particles of one color and some areas emitting particles of a different color. A special note should be made about recursive emission. Among my colleagues and I we had the rule of thumb that particles start to be interesting when emission is recursive at least three level deep. That means that a particle should be able to emit other particles which in turn should be able to emit other particles. In games this might not be needed as pervasively as we did on film, but even simple fireworks would require this feature, one way or another. The way I would do it is that in the same way an emitter might receive a circle or a box as an input to determine the area/volume where particles are born, it should be possible to use a particles component for the same purpose, so that the particles in set 2 are born in the locations of the particles in set 1.

I cannot write any more as it is 00:20 and I better go to sleep. But I will over the next 24-48 hrs.
 

manu3d

Active Member
Contributor
Architecture
Following from my previous message.

The particles component itself should hold current data, such as mass, positions, velocities and lifespan on a per-particle basis. It should also hold attributes determining visual characteristics such as type (points, lines or sprites for example), color, texture for sprites and similar attributes. Crucially, this component should be dealing with attributes changing over the lifespan of a particle. For example, an ember from a campfire starts very bright and then fades to nothing. Similarly to time-changing emitter attributes, a way to associate interpolated (or not!) lists of values to a per-particle attribute would be very useful for all but the simplest of effect. Sometimes however well defined behaviour is not the needed thing. For example one could imagine a number of point-like blue fairies over a lake. Their per-particle lifespan would be infinite, but their brightness might need to vary randomly over time. The particles component however shouldn't be concerned with how to change the positions and velocities of particles. That's up to....

Fields. Fields components determine how particles move. A directional force field would provide acceleration in one direction such as gravity. A point-based force field (with a time-varying strength) would allow for explosions and implosions. A drag field would slow down particles depending on their speed, effectively providing the viscosity of air or other fluids. Combining the fields is crucial for good-looking particles. I.e. a force field pointing down and a drag field together would be enough to simulate gravity. Very important would be noise fields, i.e. turbulence, that provide time AND (especially) space-varying acceleration/velocity to each particle. Fields might be boundless or bounded (boxes should be enough), but it should be possible to attenuate their strength (linearly, quadratically) along a dimension or simply moving away from a determined point in space.

The particle -system- would then use these three components to determine what the particles do over time. Emitters would hold lists of particle components in which to emit new (or, more likely, recycled) particles. Particles component would also hold a list of fields that affects them, with individual fields potentially affecting more than one particle component.

I'd like to conclude saying that my approach in these matter originates from having used Maya and its earlier ancestors for about 10 years. Maya is a high-end software mostly used in film and tv and I'd use it to launch particle simulations on dozens of CPUs for hours at the time for sequences only a few hundred frames long. Some of the features I mentioned (i.e. arbitrary meshes for surface emitters) might therefore be overkill in a realtime environment. Ideally we'd go through the features available in a few realtime engines to see what architectural approach were used and what features are present.

I probably forgot lots of things but I can't write more!

Ciao!
 

Linus

Member
Contributor
This is just me dumping my ideas on the forum.
I started working on a ParticleSystem module using the information provided above. The overall structure follows what @manu3d described, but there are a few places where I changed things.

First of, I believe that particle systems and particles can be implemented as entities. It allows a lot of code to be reused and it also allows for a lot of flexibility.
Furthermore, instead of directly using (force) fields and emitters, I went with function based approach.

ParticleSystemManager (or ParticleSystemSystem :p)
This is just an entity component system that updates the ParticleSystem entities.

ParticleSystemComponent
Each particle system is an entity with both a ParticleSystemComponent and a LocationComponent.
The ParticleSystemComponent is used to store the complete state of the Particle System.
It is probably also usefull if particle systems can be attached to other entities that have at least a location component.
  • list of particles: both dead and alive
  • list of AffectorFunctions: functional counterpart of fields
  • emission rate: mean + standard deviation
  • bool oneTime: do we revive particles or not?
  • nr of particles: depending on oneTime it is either the max nr alive or max nr of emissions.
  • AABB: a bounding box, so we can kill particles that are far away from the center.
ParticleComponent
Assuming we can use a LocationComponent and a RigidBodyComponent to store the physical state of the particle and
we can use the MeshComponent to store the rendering stuff, we will only need a few extra fields in the ParticleComponent
  • lifeTime: Time the particle will remain alive
  • initialLifeTime: lifeTime at emission.
AffectorFunction
At each update of a ParticleSystem, the affector functions will be called on each particle in the system.
Fields can be implemented as an AffectorFunction. AffectorFunctions can also be used to alter the color, mesh or other visual stuff of the component at each update.
The ParticleSystem can have multiple of these and they would be called in sequence.

EmissionFunction
This function is called each time a particle is brought alive. It has to set the initial values of the particle, including it's initial location, velocity etc.
Mesh based emitters, can be implemented as emission functions as well.
Recursive particle systems can be created by creating an emission function that attaches an other particle system to each particle at emission. :D


These 5 components would allow most kind of particle systems to be implemented. It is not very user friendly in it's raw form, but this can be improved by adding a number of default implementations for each component (PointEmission, MeshEmission, DirectionalForceAffector, RadialForceAffector, ExplosionParticleSystem, etc.)
 
Last edited:

manu3d

Active Member
Contributor
Architecture
I think @Immortius can probably help you more in terms of architecture in the context of the Entity System. In that context for example I don't know if the idea of Functions are more appropriate than my more component-based suggestion. Or perhaps they should be complementary? I.e. a like the idea of an arbitrary emission function that sets each particle initial attributes. But in-world emitters, especially of different shapes and dimensionality, are quite useful. Affectors functions? Sure, they could be implemented as such. As components however they could be combined with, say, a location component and also be in-world.

AABB for killing particles? In my experience particles tend to need to die on collision or at the end of their lifespan. In a realtime environment collisions might be too expensive computationally but it is appropriate to make them die in certain conditions. An Axis-Aligned Bounding Box however seems to be a bit of a blunt tool. Arbitrarily oriented (AO) planes or AO bounding boxes might be less constraining. Or perhaps you might want to consider the idea of a list of arbitrary KillerConditionFunctions that are executed every frame by the ParticleSystem, along side an arbitrary list of OnDeathCallbacks to decide what to do when a particle dies. Speaking of which perhaps the EmissionFunctions you mention above would be better named EmissionCallbacks as you trigger them upon birth or re-birth of a particle. Or perhaps Particle[Death|Emission]Subscribers, which is in line with some other concepts in the codebase.

Concerning particleS having a location component attached: normally particles are handled in world space. Even particles attached to, say, a torch, are emitted from the torch but are left behind as the torch moves. Even if there are moths flying around the torch, they might be implemented as having the same location component as the torch, but they might also be implemented using some kind of AttractorField attached to the torch which uses the location component of the torch.

Concerning the ParticleComponent, it almost seems like you are envisioning a component per particle. If I'm not misunderstanding this, I think components tend to be lightweight, but not THAT lightweight. That's why I'd group all the current data for the particles into a particleS component. Notice that a particleS component would only hold data for, say, the rain visible around a player. The particles of a campfire would be held in a different particleS component. So, no global storage for ALL the particles, to be clear.

MeshComponent for rendering stuff? Sure, if you want each particles to be a static or non-procedurally animated mesh. Many particle effects are however rendered as points, lines or sprites, which are handled directly in opengl: meshes are not involved. In those cases where do the rendering attributes go?

Finally, in realtime, particularly in the main loop, ideally nothing should really be ever instantiated. So, I don't know if you have a specific effect in mind, but particles should probably never die and always be recycled, at least within the context of a particular effect. They might not get updated, i.e. if the effect is disabled, or the whole particleS component might get deallocated, i.e. if it goes out of range. But they should never have their memory allocated/deallocated on a per-particle basis.

Hope this helps.
 

Linus

Member
Contributor
Two useful articles on this subject:
  1. The ocean Spray in your face
  2. Building an advanced Particle System (refers to 1)
Thanks manu.

Maybe I have a bit of a bias towards a more functional style of programming :p.

Meshes might not have been such a good idea.

About the AABB: their goal is not to create a visually compelling effect, but instead it is just to be able to have an absolute boundary for your particles. They are indeed blunt, but that is not much of a problem as long as they are large enough that the particles rarely hit this boundary. Article 2 also points out that is useful to have to reason about whether or not a particle system is visible. Maybe it is not really necessary to kill particles that are outside the AABB. :confused:
KillerConditionFunctions would just be Affectors that set the lifetime of particles to zero I suppose.

Storing the particle data in the particleS does indeed seem more efficient. I am not sure how that would work with collisions though, since the only way (that I know of) to enable physics on an object is via a RigidBodyComponent. I should take a look at how this is done in the current BlockParticleSystem.

Edit:
...particles should probably never die and always be recycled..
We seem to attach different meanings to particles marked as dead. For me it just means that the particle is not visible/updated anymore and that it can be recycled. So what you described about particle re-use was actually the same as what I had in mind :D.
On a side note: It might even be beneficial to do the recycling of particles at the SystemManager level, so similar systems can share the same pool of particles.
 
Last edited:

manu3d

Active Member
Contributor
Architecture
Concerning collisions, well, you'd have to write your own collision handling. Using a whole rigid body for a single particle is like shooting a mosquito with a cannon. Luckily, if the particles can be approximated to points, lines or spheres collisions are not as bad as when you have to deal with arbitrary meshes or even simple boxes.

Anyway, I see you have a path to follow. I look forward to the first screenshots. ;)
 

Immortius

Lead Software Architect
Contributor
Architecture
GUI
My thoughts:

Firstly, I think that individual particles should not be entities. Particle effects is an area where optimization is important because you are dealing with potentially hundreds of particles per effect - which means that you're probably batching them in meshes within the particle system itself. Events could still be used to determine movement of particles (probably batched) or effect on collision - by sending an event with the particle relative/absolute coords, scale, etc attributes - then you could have components + systems to drive attractors, etc. I am assuming here that particles are mostly for display purposes and it is fine if a particle effect is reset over a save/load transition. Alternatively the particle attributes could be stored in the main particle effect component.

It would probably be a good idea to determine the attributes of particles. I imagine position (which may be absolute or relative depending on a property of the particle effect, to allow for trails or not as desired), scale (uniform/2d/3d?), velocity, rotation and maybe tint?

In the past using particle systems in other engines, I've found it useful to be able to apply arbitrary materials to particles. Arbitrary mesh... less so, but potentially. If arbitrary mesh are supported, then there needs to be an option to have the particles always face the camera or not.

For collision, the particle system could use the physics system more directly and maintain colliders internally rather than requiring entities per particle. Or it could use one of a number of simpler collision check techniques, such as traces.
 

Linus

Member
Contributor
I was able to produce some code over the weekend, using the ideas/guidelines posted in this thread.

I uploaded an implementation of a particle pool on my fork on Github, which keeps track of all particle data and
allows for recycling of particles without any additional allocations.

Following your advise, particles themselves are not entities; only emitters and particleSystems are entities.

I continued working until I got my first particle system on screen:
Terasology-150302033706-1920x1017.png
 

Linus

Member
Contributor
Update:

I'm looking for a bit of feedback :). The particle system is nearing completion. Updating and rendering logic is pretty much done. I just need to clean up the code and tie some stuff to the entity component system.
I cannot yet use textures yet, but it shouldn't be too hard to add that in. Maybe I'll do that after the initial PR. Luckily, pure quads do not look out of place too much.
Initial PR will probably not include recursive systems. I have not yet looked at how to design a clean interface for that. For now, you'll just have to do these manually by controlling the emitters with some external system :p.

As an example of what is currently possible, here is picture of a simple fire/smoke particle system:
Terasology-150310114845-1152x720.png

Edit: block collision works too (99% of the time). Emitter under a ledge:
Terasology-150310131756-1152x720.png

And here is how this particular particle system was defined in java: pastebin. :geek:
This should give a basic idea of how you would use the system from a module.
It would be cool if this could all be done outside of java with a prefab file, but that is not possible yet.

There is still a bug with blurring. Blur is determined by the distance of the blocks behind the particles. :(
Terasology-150301193254-1152x720.png

Maybe RenderSystem.renderAlphaBlend should be called after blurring has been applied?

Bonus picture:
Terasology-150309003942-1152x720.png
 
Last edited:

Skaldarnar

Badges badges badges badges mushroom mushroom!
Contributor
Art
World
SpecOps
Great work @Linus ! The fireplace looks awesome :D

We need to turn that pastebin to a wiki page and explain all the basic features. Defining them this way in Java looks quite nice, I can't wait to try it for the magical sphere in LaS :)
 

manu3d

Active Member
Contributor
Architecture
I like how the simple rendering style, as you say, fits very well within the context of a block world. So, for what I can see: thumbs up!

The Depth of Field blurring problem for semi-transparent triangles is a known one (issue #1591) and as you'll see from the discussion I agree with Immortius that it's not something the current renderer can deal with correctly. I guess we could do as you suggest, but then everything opaque would get appropriately blurred and everything even just a little transparent, even in the distance, would remain sharp, hardly an improvement. I still don't know the renderer enough though, a proper opengl/shaders wizard might know a way.

Luckily I don't think many people actually play with the DoF active (?) it's more of an effect for cinematic purposes, and if you want to make a movie then you can choose camera angles for which the effect works.

Concerning the pastebin usage snippet, looks like a good start. I'm wondering what it will look like once Entities and Components come into play. If there is one thing I'd do differently given your architecture, I'd make the Energy*Affectors accept an array or something similar defined elsewhere rather than use multiple .gradientMap.put statements. This would also allow the same array to be reused elsewhere.

Also, opengl has a number of very useful facilities when dealing with particles, so that the cpu is left with little to do and most things are done in shaders, taking full advantage of the GPU's parallelism. If your code is not already fashioned that way, you might want to look into it.

Again, looks good!
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Awesome work! :) I'm especially happy about the fancy extra with particles not going through ledges (reminds of of @Josharias work to make machines you have to vent or your house will fill with smoke that'll kill you!)

As for blur and such, if we're unhappy with how it currently looks but not expecting a fix soon we could always move it to an experimental setting that's off by default. Is DoF == FoV ? I forget .. That's on by default and can't be disabled via settings, it seems. Blur is on normal and default overall is the "Insane!" preset. Maybe we should consider reshuffling what is active where, and to what degree (less blur?), we haven't done that for a long time. Might be an idea to start on "Epic" too so we begin at more mid-range settings.
 

Josharias

Conjurer of Grimoires
Contributor
World
SpecOps
Yeah, I gotta bring back the dangerous smoke fog death. Specially with a cool particle system like this!
 
Top