Category:Particle System

From Valve Developer Community
Revision as of 22:47, 3 July 2008 by Mdurand (talk | contribs)

Jump to: navigation, search

Overview

  • What is a Particle System?
You probably have a good idea of what a particle system is if you're here, however within the context of Source there are a number of particulars that we'll need to be establish first. The particle system fills a variety of roles that may have been specialized hard coded systems in the past. It is a generic sprite and beam based effects system that will also cover fullscreen and post-processing type effects as it matures.
A particle system often includes a number of nested child effects, each of which are made up of plug-in components that control the behavior of the system. This allows for each particle effect to be as simple or as complex as needed.
  • Getting Started
To create particle systems, simply run the game with -tools and select the particle editor tool.
Particle systems are stored in .pcf files. Any system which references another system (such as a child) must be stored within the same .pcf file. Beyond that, these are simply for organization - each file can contain as many or as few actual systems as desired.
All .pcf's must be in the particle_manifest.txt in the particles folder to be used by the game. Other than this, all particle systems are always accessed by the system name, never the .pcf name.
  • The Editor
The upper left pane of the editor displays the currently loaded .pcf. You can select, create, copy and paste systems from here.
The lower left is the working panel. You edit all particle properties here. Generally, it's easiest to select the various subsystems through the dropdown menu, but you can also edit the system through the tree view under the base properties window.
The lower right window is the preview pane. The left button spins the system around, the right zooms, and the middle allows translation movement.
The upper right is the game pane. If a level is loaded, this shows the current view. To switch to this view, use the f10 and f11 keys (one toggles the controls, the other toggles fullscreen).

What is a particle system made up of?

  • Memory Fields
To understand some of the hows and whys behind the particle system's components, it helps to explain a bit of its technical organization. Particle systems are designed to conserve memory with the trade off of some extra computation. To this end, each particle within a system stores a limited number of fields that describe it. These fields include aspects like position, lifespan, color, rotation, etc. Based on these properties, the components that control the particle system compute each particle's current state each frame.
  • Control Points
Control Points (CPs) are the basic external input mechanism for a particle system. Each system can have up to 64 control points that it can access. Control points have a position, orientation, and an entity they can reference. By default, control point 0 is the particle system's origin, and it's orientation is its facing. If it's associated with an entity, it can be parented to the entity or an attachment point.
In this same way, each additional control point in a system can be assigned a position in space, an orientation, and an entity. This allows systems such as the TF Medic's heal beam to travel between the weapon and the player it is healing.
This can also allow a single system to emit across multiple point or model sources if necessary, to provide an effect such as a growing fire, for example.
As the various elements of a particle system can access CP data, this can allow multiple dynamic elements to influence a system. While control points act as a position in space by default, other data can be stored in each point if needed, which allows external code or entities to pass generic data into a system that can then be remapped to properties of the system.
  • Base Properties
In its base state, a particle system has no components, just a few basic properties. These are the generic properties that every system has. They include things which affect a whole system, which don't vary on a per-particle basis and don't fit into the other sockets which make up a system.
  • Components
Beyond the base properties, a particle system is made up of component pieces which are socketed in. In the general case, you can have as many of these elements in each category as you wish, even socketing in multiple copies of the same component when it makes sense to do so. These act upon the fields that each particle has in order to set up or modify it.
  • Renderers
Renders define how your particles get drawn. These include sprites, ropes, streaks, and so forth. Each particle can be drawn multiple times in multiple ways if you wish to do so.
  • Emitters
Emitters define how many particles are created over what period of time. Again a system can have multiple emitters which define different types of emission which come together to form the overall pattern to the particle emission.
  • Initializers
Initializers set up the starting state for each particle that is created, initializing the fields within each particle. For example, a particle's initial location in space, it's color, size, or alpha. Initializers only set up starting properties of each particle as it is created, after which they have no effect on each particle.
  • Operators
Once the initial state of a particle has been set up by Initializers, operators take up the act and carry out a function upon each particle for every frame that it exists.
  • Forces
Forces are a variation on operators that affect motion of the particle.
  • Constraints
Constraints define movement limits on a particle, such as collision or maximum distance from a control point.
  • Children
Children are simply other particle systems which are linked to this system. Some data, such as control points, can be passed down to children, and they can be nested multiple levels deep.

Creating your first System

Often times you'll end up taking an existing system, copying it, and simply modifying it to fit your needs. However, to create a system, just hit the "Create" button and enter a name for your system.

You've now created an entirely empty system. Without any of the plugin components it will do nothing. There are a few basic components you'll have to add. So lets get started.

First add an Animated Sprite Renderer to allow it to render.

Next, we'll want to specify where they are created, so go to the Initializers and add a Position Within Sphere Initializer. Let's give them a min and max speed of 64. Without setting up an initial position, particles won't know where to spawn properly.

Now add a Continuous Emitter. You should see a white square appear. You're actually emitting a ton of particles with the default texture.

You'll notice that even though you've given them an initial speed, they're not moving. There are also a ton building up. That's because they have no operators. So even though you're setting up an initial position and speed for them, nothing is being processed after that except for rendering.

So we'll need two operators. One is the Movement Basic operator. This allows particles to move. The other is a Lifespan Decay operator. This kills particles once their lifespan is over. Now you should see your particles moving and disappearing after a second. By default particles have a one second lifespan.

A particle's lifespan is initialized on its creation, so in order to change that, let's add a Lifespan Random Initializer.

Almost all Initializers and operators have randomized ranges for their settings. So if we want our particles to last between 2 and 4 seconds, we can enter and min and max of 2 and 4.

Next, let's change the texture to not be a white square. Go to the base properties and click on the material to bring up the browser and select a more appropriate particle material.

Note:Particle materials should use the SpriteCard shader.

Finally, let's add a Fade Out Random operator. This will cause the particles to fade out over a random range of their lifespan, which by default is the final 25%. It's important to note that since this is determined by the lifespan of the particle, the final 25% will be different depending on what the particle was initialized at in the range between 2 and 4 seconds (i.e. anywhere between the last .5 and 1 seconds).

Particle Performance

Max Particles

By default each system is set to 1000 max particles. This much memory is allocated for the system regardless of whether it's used or not. So after setting up your system, you'll want to take a look at the counter to see how many particles you're using and set the max particles to this number. This will help to keep the memory usage to a sane amount.

Threading

Particles are multithreaded by system. So if you have multiple systems, they'll be distributed over as many threads as are available. So on its face, it's good to split complex systems up into multiple systems to take advantage of this feature. That said, there's overhead to each system, so there's a limited benefit to the usefulness of this approach, especially on simpler systems. Splitting up a system that only has a few dozen particles will almost certainly be a net loss. However, if you system has in the thousand+ range of particles, it's worth treating it as multiple lower count particle systems which can be multi-threaded. A system and it's children are always on the same thread because parents and children can pass data to each other and as such need to be be grouped together.

SIMD

Right now, most particle operators, Initializers, etc. work in SIMD. This means on current hardware they're generally doing all math on groups of four particles simultaneously. Theoretically in the future this will scale up to wider numbers on different kinds of hardware. The point here is that if you stick to multiples of four, you'll be making better use of the system. Scaling a system down to the closest multiple of four will make it slightly more optimal. This isn't a huge gain, but it's something to be aware of.

Overdraw

Overdraw is caused by having to redraw the same pixel many times over, due to many layers on top of one another. Particles are a common culprit, and it's relatively easy to run into a worst case scenario of many sprites directly on top of one another taking up the entire screen. There's a few ways to combat this within the particle system.
The starting point to avoid this is general good practices, such as using fewer, smaller, more opaque particles, rather than many very translucent ones. However, depending on the usage case, that's not always possible.
So there are some useful .vmt material parameters which can be helpful. A pair of them are $minfadesize and $maxfadesize. These cause a particle to begin/end to fade based on its percentage of screensize. So for example a material with a $minfadesize of .25 and $maxfadesize of .5 would start to fade if it were 25% of the screen size and be entirely faded (and not render) once it hit 50% of the screensize. In the case of walking through dense particle based smoke this could make the difference between fast framerates and overdraw death.
Another useful parameter is $maxsize. This is a maximum size, in screenspace, that a particle can reach. It is capped at this size. So for example, if you need to see blood for hit registration purposes, you can't have it fade, but you can cap how much of the screen it'll take up, thus reducing the potential overdraw.
Conversely there's a $minsize parameter. This is less of a performance option as a visual one. It can limit the minimum size, in screenspace, of a particle. So to use the example of blood again, you may want it to always be at least some minimum size, so enemies shot a very far way away will still have a visible effect. Setting the minsize will accomplish this.
The two can be used together for other interesting effects. For example, we use dust motes in a few areas which are limited to a very small min-max range. So at a distance you see these sparkling pixel sized motes floating in the air, but they don't grow to be golf ball sized bits of fuzz in the air when you approach them.
Depthblending makes particles look nice and smooth when interpenetrating surfaces. However, it's also more expensive for fillrate. So setting $depthblend 0 in the .vmt can help to improve performance where needed.
One additional useful .vmt parameter for animated texture sheets is $blendframes 0/1. By default animated textures blend between any given two animation frames to increase the apparent animation rate. However, this adds additional overdraw to the scene. Disabling the frameblend will result in less smooth animation, but increased performance.

Sharing data

There are a variety of ways to share data between parent and children systems. Some of the more complex Initializers or operators can minimize their performance impact by writing out their results to a control point, which can then be read by children and use the same data without having to do any of the work.

Collision

In general, collision is an expensive operation. The default mode 0 does traces for each particle every frame. This is expensive and doesn't scale well. However, the Collision constraint allows for a few different collision modes which allow for much faster collisions that trade off accuracy for speed. Collision Mode 3 is the best accuracy/performance tradeoff for dynamic collisions with particles in unpredictable locations/movements.

Creation

Particles must be added to the GAME\particles\particles_manifest.txt file. To make dx8-level fall backs for particle systems, if you have a file in your manifest, like "rockettrail.pcf" for example, if you make a file called "rockettrail_dx80.pcf", then it will be loaded instead of rockettrail.pcf on low-end machines.

Specialized Particle Systems

Application

Subcategories

This category has the following 2 subcategories, out of 2 total.

P

Pages in category "Particle System"

The following 77 pages are in this category, out of 77 total.