Particle tutorial smoke

From PopcornFX
Jump to: navigation, search
For PK-Fx Editor version : 1.4.0 and above
Main page: Particle tutorials

In this tutorial, we'll see:

  • How to create a new particle effect from scratch
  • Basic navigation controls in the realtime editor
  • How the particle billboard renderer works
  • How to use a texture atlas
  • Basic scripting
  • How to add new evolvers
  • How to rotate particles
  • How to control particle size and color with a custom curve
  • How to create a thumbnail of our effect for the content browser
Smoke effect
Final result

Creating a new effect

To create a new particle effect, when inside the content browser, right click on an empty area of the 'Content Thumbnails' panel, and select 'Create Asset' > 'Particle System'

Tut01 01.jpg

A window will pop, asking you the name you wish to give to the new particle effect:


Once validated, A new thumbnail will appear on the content browser's list.

Tut01 02.jpg

Double click on the new thumbnail to startup the particle editor.

Navigating in the realtime editor

See the Particle editor overview for details on the interface.

basically, in the realtime viewport:

  • middle mouse click (wheel) + mouse move : pans the camera around
  • right mouse click + mouse move : rotates the camera, allowing tou to look around the scene, FPS-like
  • mouse wheel scroll : moves forward/backwards. [CTRL] and [SHIFT] keys act as modifiers to make the movement faster or slower.

When you use the right mouse click, FPS camera controls with [W] [A] [S] [D] keys are activated, and you can move around the scene. they are deactivated as soon as you release the right mouse button.

When the particle editor fires up after having created an effect, you will see the default particle effect running in the realime viewport. This simple effect has one layer, one physics evolver, a spawn script, and a billboard renderer set to additive mode with a default texture.

Also, a quick tip is displayed on the viewport: "Press space to spawn particles"

Tut01 03.jpg

However, if you try pressing space, nothing will happen.

that's because there is no backdrop yet.

The particle editor allows you to specify a backdrop for your effect. this will only be used in the editor, the effect isn't linked to that backdrop whatsoever, it is just an editing aid. You can also import custom backdrops.

On the bottom of the node properties panel (the top left panel in the default layout), you will see different tabs, namely:

  • Node properties
  • Environment
  • Trace report

If you click on the Environment tab, right on top is a list of backdrops. 'None' is selected. try selecting another one. in this tutorial We'll use the 'CubeRoomDark' backdrop

Once the backdrop has appeared, pressing space inside the realtime viewport will instantiate the effect in the scene, where the mouse pointer is:

Tut01 04.jpg

Press the reset Radiation.png button to reset the particle system instance to the origin.

Useful navigation/viewing tip inside the realtime viewport
in addition to the fps look with the right mouse button, there is an orbit mode that allows you to rotate around an arbitrary point inside the scene.
Hold [ALT] + [SHIFT] and middle(wheel)-click + drag the mouse, the camera will orbit around the point in the scene that was under the mouse when you right-clicked.
Without a backdrop loaded, the camera will rotate around the origin.

Other useful commands are:

  • [F2] / [SHIFT]+[F2] : cycle back and forth between pause modes
  • [F3] / [SHIFT]+[F3] : cycle back and forth between render modes

Setting up the billboard renderer

First, to create a smoke effect, we're going to change that default texture and material.

In the particle treeview, under ParticleSystem > CActionFactory > Renderers, select the CParticleRenderer_Billboard CParticleRenderer Billboard.png node. The node properties panel will display the billboard renderer's properties.

By default, 'BillboardingMaterial' is set to Additive. but smoke isn't additive. we're going to change that to AlphaBlend_Additive_Soft. We could use the classic 'AlphaBlend' material in the list, but this one has several advantages, it has soft fade-out at intersections with geometry (soft particles), and it can be used to render both additive and alpha-blended particles.

As it is easier for the engine to batch together particles from different layers if they share the same material and textures, using this material allows us to have a single material for a whole effect, even a complex one, and improve performance.

This material is a bit different from the standard alpha blended or additive materials, here are the blending functions:

BillboarderMaterials TemplateRGB.png BillboarderMaterials TemplateAlpha.png BillboarderMaterials TemplateBackground.png
SRC = texture color modulated by the particle color A = texture alpha modulated by the particle alpha DST = framebuffer color

  • BillboarderMaterials Additive.png Additive = SRC * A + DST (Linear Dodge in Photoshop)
  • BillboarderMaterials Additive NoAlpha.png Additive_NoAlpha = SRC + DST (Linear Dodge in Photoshop)
  • BillboarderMaterials AlphaBlend 0.png AlphaBlend = SRC * A + DST * (1 - A) (normal Opaque blending in Photoshop)
  • BillboarderMaterials AlphaBlend Additive Soft.png AlphaBlend_Additive = SRC + DST * (1 - A)

Basically, in AlphaBlend_Additive mode, the source color is premultiplied alpha. the alpha channel can be seen as an opacity coefficient that will darken the scene behind the particle, and the color as the emission color.

Tut01 05.jpg

The default billboarder does not set a texture, it uses the hh-fx editor's default texture is used for that material, so you will have to change that. there are two texture fields in the default billboarder : 'Diffuse' and 'Normal'.

'Normal' is only used in the lit materials. if you click on the 'Diffuse' box, a texture resource selector will appear, and let you browse the textures inside the current pack hierarchy. if you hover the mouse over a texture name, a small tooltip will appear, showing a preview of the texture, and some basic information, such as its dimensions, and path.

For this example, we'll use a texture atlas used in the particle samples demos coming with the editor, that contains a few useful textures: some smokes, sparks, and animated flames.

In the texture resource selector, select the "" texture

Tut01 06.jpg

You will notice that the texture is updated in the realtime viewport. Also notice the particle node editor at the bottom, showing a preview of the texture. As expected, the whole atlas gets mapped onto the whole billboards, but we definitely don't want that:

Tut01 07.jpg

As far as it's concerned, the billboard renderer thinks the texture we just gave it is a texture for a single sprite. we will need to tell the billboard renderer how the texture sheet is split into sub-textures.

In the renderer properties, click on the 'AtlasDefinition' box, just below the 'Diffuse' and 'Normal' fields. the resource selector will appear again, and this time it shows .txt files. Select the "BlastPack_Extended.txt" file.

Tut01 08.jpg

the rendering is updated again, and this time it only shows a single element of the atlas ! the particle node editor now displays red boxes with numbers above the texture preview, showing the sub-textures rectangles loaded from the atlas definition file.

A quick note here if you want to create your own texture atlases: The atlas builder in the previous versions of the editor has been removed, but we will soon make an update where you will be able to use it again. in the meantime, here is how the atlas definition files are expected to be written:

  • one line per sub-texture
  • 4 values per line, separated by commas
  • the decimal point is a dot, not a comma
  • the values are normalized texture coordinates, between 0.0 and 1.0
  • the values are in the following order: left corner, top corner, right corner, bottom corner

for example, for a 2*2 texture atlas containing 4 equal-sized squared textures, the atlas definition file would look like:

Tex 2x2.png
0, 0, 0.5, 0.5
0.5, 0, 1, 0.5
0, 0.5, 0.5, 1
0.5, 0.5, 1, 1

Of course, the sub-rectangles can be anything, the whole texture doesn't have to be covered entirely either:

Tex 3x1.png
0,     0, 0.333, 0.5
0.333, 0, 0.667, 0.5
0.667, 0, 1,     0.5

Tut01 09.jpg

Now that we gave the renderer a complete atlas (texture + sub-rect definition), it is time to use it and specify which textures we want mapped on which particles.

If you take a look at the particle treeview, you will see inside the layer, a line named 'CParticleDescriptor.png Fields', click on it, and the node properties panel will display all the elements a particle has in this layer.

If you looked at it before setting the atlas definition, and if you look at it now, you will notice a new field appeared, named 'TextureID':

Tut01 10.png Tut01 11.png
Without an atlas definition With an atlas definition

This Field has been added automatically by the billboard renderer. It is a field it needs to know what sub-rect it has to assign to the particle when it's going to render it.

By default, every unassigned field is cleared to zero. that's why all our particles are rendered with the first sub-texture, 'TextureID' is equal to 0, which means, the first sub-texture.

We'll see in more detail what this panel shows and does further down, when adding some color to the effect.

We now want to tell the billboarder to use a specific sub-texture, so we must find a way to change the 'TextureID' field of the particles.

In the layer, under the renderers, there is a node called 'CCompilerSyntaxNodeExpression.png Spawner Script'.
Select it:

Tut01 12.jpg

The node editor panel now shows the script editor. by default, when new layers are created, the spawn script is of the form:

function void	Eval()
	Life = 1.0;
	Size = 0.25;

This just makes all particles live for 1 second, and sets their size to 0.25 world units. To change the 'TextureID' field, just add the following line:

	TextureID = 33;

Save the script using Ctrl+S. Please note that it also saves the whole particle effect
When the script is saved, it is rebuilt on the fly, and you see instantly the effect of your changes inside the realtime viewport.

You will notice that when the script is first opened, or saved after a modification, the lines are slightly colored in green.
This is a performance estimate, the possible line colors range from very light green (it will be fast to execute) to heavy red (will be much slower if there are a lot of particles)

Tut01 12 sc01.png

for example, copy/paste the following into the TextureID:

	TextureID = pow(wavetri(spawner.LifeRatio + 0.1*length(rand(-0.6.xx, 0.6.xx*sign(spawner.LifeRatio)))),2)*31.99;

When saved, the line will become slightly orange/red, meaning it's probably a good idea to try and simplify the line.
You can see additional stats about the script by clicking on the status bar below:

Tut01 12 sc02.png

Tut01 12 sc03.png

If for some reason the script couldn't be built (most likely a syntax error), the script editor's status bar will show an error.

For example, if you remove one of the closing parenthesis in the complex line above, you will see:

Tut01 12 sc04.png

Tut01 12 sc05.png

You can find more information and details about the scripting language and the script editor, on the Scripting reference page.

Back to our smoke, we can add a small upward velocity that will be used by the physics evolver, and boost the life up to three seconds to make the smoke plume a bit higher:

This gives us the following spawn script:

function void	Eval()
	Life = 3.0;
	Size = 0.25;
	TextureID = 33;
	Velocity = float3(0,0.5,0);

And the following result:

Tut01 13.jpg


As you can see, the smoke looks extremely repetitive, all the sprites have an identical orientation. So to improve things a bit, we can try randomly rotating them. To do this, we have two options:

  • manually create a new particle field of type float, assign it a random value inside the spawn script, and tell the billboard renderer to use it as a rotation angle.
  • add a rotation evolver, that will automatically create a 'Rotation' field, then assign a random value inside the spawn script. by default, the billboard renderer uses a field named 'Rotation' as the rotation angles source.

we'll go for the second solution, as it will allow us very easily to make the particles rotate dynamically during their lifetime. To create a new evolver, right-click on the 'State_0' node, inside the particle treeview, then select the 'New Evolver' menu, and a list of all available evolvers appears.

by default:

Evolver name Description
CParticleEvolver Spawner.png CParticleEvolver_Spawner used to create trails. this evolver will spawn other particles
CParticleEvolver Field.png CParticleEvolver_Field Binds a curve to a particle property
CParticleEvolver Script.png CParticleEvolver_Script Runs a custom script at each evolve step
CParticleEvolver Rotation.png CParticleEvolver_Rotation Updates particle rotations, given a rotation speed
CParticleEvolver Damper.png CParticleEvolver_Damper Damps any field over time
CParticleEvolver Physics.png CParticleEvolver_Physics Handles velocity / gravity / acceleration / collisions. main evolver for moving particles around. this is created by default in each new layer
CParticleEvolver SPH.png CParticleEvolver_SPH Experimental, temporarily disabled in the current release.
CParticleEvolver Flocking.png CParticleEvolver_Flocking Adds autonomous flocking behaviours to the particles
CParticleEvolver Containment.png CParticleEvolver_Containment Constrains the particles to an area

We're going to select CParticleEvolver Rotation.png CParticleEvolver_Rotation:

Tut01 14.jpg

After selecting the 'CParticleEvolver_Rotation' evolver, we can see two new fields in the particle field list:

  • Rotation
  • ScalarRotationSpeed

To assign a random value to the Rotation field, we're going to use the rand() function inside the spawn script.
The rand function takes two parameters, and returns a random number uniformly distributed between these two values.
The two values must be of the same type, and can be a float, float2, float3, or float4.

for example, if we want a random value in the -pi, +pi range, we can write:

	Rotation = rand(-pi, pi);

Setting up a random rotation speed gives us this script:

function void	Eval()
	Life = 3.0;
	Size = 0.25;
	TextureID = 33;
	Velocity = float3(0,0.5,0);
	Rotation = rand(-pi, pi);
	ScalarRotationSpeed = rand(-1.5, 1.5);

Note that you can also try randomizing the velocity:

	Velocity = rand(float3(-0.2,0.5,-0.2), float3(0.2,1.5,0.2));

This actually samples a random cube of size {0.4, 1.0, 0.4}, centered at {0.0, 1.0, 0.0} But as we'll see in a later tutorial, there are much easier ways to sample a cube, using shapes.

Tut01 15.jpg

It looks better, but we are still using a single texture for all our smoke particles ! There are actually 4 different cloud textures in this texture atlas. If you select the particle renderer again, you can see they have IDs 32, 33, 34, and 35. If we want to randomly pick one of these four images, instead of:

	TextureID = 33;

We just have to write:

	TextureID = rand(32, 36);

note that if you randomize between 32 and 35, there will only be three textures selected. as the rand() function expects floating point values, the value '36' will never be reached. The line above is roughly equivalent to writing:

	TextureID = rand(32, 35.9999999);

which actually maps to indices 32 to 35 included.

Tut01 15b.jpg

Now, this smoke plume is a bit boring, all particles have the same constant size set inside the spawn script. We're going to change their sizes over time. In order to do this, a fast and easy way is to use user-defined curves. Right click again on the 'State_0' node, and add a 'Field' evolver:

Tut01 16.jpg

This will add a new node inside the current particle state, named 'Spline'. when selecting this new node, you will notice a spline editor appears in the node editor panel at the bottom of the window.

For help about using the spline editor, see the page Spline editor

In the treeview, double-click directly on the right of the text 'Spline', an edit-box will appear. Now the name of the particle field you want to bind this curve to. here, we want to change the sizes, so just type 'Size'.

The realtime preview will update automatically, and the particles should disappear. This is because by default, our new curve is set to zero:

Tut01 17.jpg

When the spline is first created, it has two control-points (keyframes), the first one at time t=0.0, on the left hand-side of the graph, and the other one at time t=1.0, on the right hand-side. Splines in the evolvers are sampled using the particle life ratio, that's equal to 0.0 at particle birth, and 1.0 at the end of its life.

As soon as you move the curve's control points around, the particles should become visible again.
You can use middle-mouse click & drag in the spline editor to pan the spline around.

If we move the end control point to a larger value than the start control point, the particles will become bigger as time goes on. You can also change the control point's tangents to change the shape of the curve. don't forget to have a look at the Spline editor page for more details about controls and navigation inside the spline editor.

Just a quick overview of the basic controls:

  • zoom in/out : mouse wheel (hold the CTRL key for faster zooming)
  • move the view around : drag the mouse around while holding the mousewheel/middlebutton down.
  • nonuniform scale : drag the mouse with the wheel down, while holding the CTRL key

Tut01 18.jpg

Allright, the sizes evolve a bit better now, but what if we'd like to change the particle colors?

The default billboard renderer can read a particle field for color information, by default, this field is configured in the renderer to be named 'Color' (you can change that if you want, that's useful for compound renderers, more on that in a later tutorial).

But by default, there is no field named 'Color', so we're going to add a new field. In the treeview, select the 'Fields' node inside the particle layer. The particle fields should appear in the node properties panel.

See the Particle fields page for a detailed description of the particle fields panel.

To add a new field, click on the 'Add' button. A new window pops, asking you what field you'd like to add. There are various presets for often-used fields, one of them is already filled-out for 'Color':

Tut01 19.jpg

After selecting it, you should see the 'Color' field in the fields list. Now, let's create another Field evolver in State_0, and bind it to 'Color', by double-clicking next to the 'Spline' node, and typing 'Color'.

By default, as before, the created spline only has one dimension (a single curve), but the 'Color' field is of type float4, which means each color contains 4 float values, one for each R, G, B, and alpha components. Therefore, we need to change the curve dimension and increase it to 4. any other value will be treated as invalid, and the evolver will simply ignore it.

To change the spline dimension, right click on an empty area in the Spline editor, go into the 'Curve Dimension' menu, and select the dimension you want. In our case, 4 :

Tut01 20.jpg

You will instantly see the spline editor change, there are now 4 curves, 4 filter buttons on the top, and the particles disappeared again

Like for the sizes, it's normal for the particles to have gone invisible. by default the spline values are all zeroes, that means alpha to 0 as well. move the keyframes around, and you should see them reappearing:

Tut01 21.jpg

By adding new control points (Alt+click in the spline editor to add a new keyframe under the mouse pointer) we can experiment a bit and get more interesting results.

Tut01 22.jpg

Tut01 23.jpg

Packing up

Here are a few details to be aware of:

By default, any newly created particle system has a single spawner that lasts for 2.0 seconds, and the editor is configured to make the effect loop every two seconds.

If you select the particle layer, you'll gain access to the spawner properties. If you check the 'Infinite' checkbox, the spawner will last forever, instead of killing itself after two seconds, but the editor still loops the effect and respawns it every two seconds. after a minute you'll have 30 effects spawned on top of each other, and it'll start to look like this:

Tut01 24.jpg

to fix the problem, just uncheck the Loop.png loop button in the particle editor viewport's toolbar, and reset Radiation.png the scene to clear the excess effects.

to play around and see what the effect looks like on walls or with multiple other effect instances around, move the mouse over the realtime viewport, and press the [SPACE] key. This will spawn a new instance of the effect on the scene under the mouse cursor:

Tut01 25.jpg

By default, if you close the particle editor, go back to the content browser, and open it up again, the view will reset to its default coordinates:

Tut01 26.jpg

You can tell the editor to save a default startup view location for this effect at any time by clicking on the eye icon on the left of the realtime viewport top toolbar.

From now on, the editor will start at this location, and you can reset the view to these settings at any time by clicking the 'Reset' button on the realtime viewport's bottom toolbar.

Tut01 27.jpg

As you might have noticed, the content browser also has no thumbnail for the effect, and displays a "No Preview" image. you can capture a thumbnail by clicking the Capture Thumbnail icon, on the left of the eye icon, on the realtime viewport's top toolbar.

The content browser will update itself with the thumbnail.


Note: currently, the thumbnails are only automatically refreshed once, when there was no thumbnail before. If you capture thumbnails multiple times, you will need to explicitely refresh the content browser to see the changes. you can do that by unchecking/re-checking the "Filter by resource type [_] Check All" checkbox.

Next tutorial : Particle tutorial fire