Particle tutorial fire

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

In this tutorial, we'll see:

  • How to create multiple particle layers
  • How to setup light particles
  • How to use animated textures in a texture atlas containing the different animation frames
  • How to setup the turbulence sampler

For this tutorial, we are going to start from the effect created in the smoke tutorial

Tuto2 preview 1.jpg

Final result

Light particles

First, we're going to create a new layer. In order to do this, right-click on the main 'Particle system' node in the particle treeview, and select 'New layer'.

Tut02 01 0.jpg

A new layer will appear. Reset the effect (Radiation.png) to see the new layer.
If you configured the Effect to be infinite in the previous tutorial, make sure you do the same for this new layer, by checking the 'Infinite' box in the layer properties, in the node properties panel:

Tut02 02.jpg

You can roll-up the layers to make the treeview cleaner to the eye, and rename them to more sensible names by double-clicking on their default generated names:

Tut02 03.png

As the lights we're going to create will be static and won't be affected by physics, we won't need the physics evolver, so go ahead and delete it, either by:

  • right-clicking on it and selecting 'Delete'
  • selecting if with a left-click, and hitting the [DELETE] key

Tut02 04.jpg

Once the physics evolver has been deleted, the new particles will stop moving.

We're also going to need a new Color field, and a color curve. If you're not sure how to create these, please see the smoke tutorial

Tut02 07.jpg

Now, for light particles, we don't want a billboard renderer, but a light renderer, so delete the 'CParticleRenderer_Billboard' node in the 'Renderers' section of the 'Lights' layer.

Then, right click on the 'Renderers' node, and select 'CParticleRenderer_Light'

Tut02 08.jpg

Right now, you shouldn't see anything, as the lights should be spawned on the ground plane, and are a bit too small, so we're going to select the Spawner Script, and change the size from the default 0.25 units to 2.5, and set the spawn position to something like float3(0,0.2,0):

function void	Eval()
	Life = 1.0;
	Size = 2.5;
	Position = float3(0,0.2,0);

You should see a small white light shining on the ground:

Tut02 09.jpg

After tweaking the color curve to make the light more reddish, and spawning some additional effect instances with the [SPACE] key, the effect should look like this:

Tut02 11.jpg

the hh-Fx editor provides a view of the internal engine's deffered buffers, and it can be useful when working with light particles, as you have access to the light-buffer, and can see more clearly the lights.

Hit [F4] multiple times to cycle through the intermediate render buffers, until you arrive at the one named 'Irradiance':

see the Debug render buffers page for a full description of available debug buffers

Tut02 12.jpg

Just keep hitting [F4] to wrap back to the full rendering.

Now, something to be aware of is that by default, when creating a new layer, the generated particle spawner spawns 20 particles per second. Each light particle lives 1 second. This means that for a single instance of the effect, we've got 20 light particles. In the screenshots below, there are 8 instances spawned, that makes it 160 lights onscreen.

It's not necessarily bad, but in the current case, it's just plain useless. Select the 'Lights' layer, and lower the 'SpawnCount' value to around 1 particle per second:

Tut02 14.jpg

As our color/intensity curve is smooth, we still need a bit more than one particle per effect at any given time to have a smooth feeling, so we're going to bring the life of the light particles up a bit. just tweak that until it looks allright. between 2 and 3 seconds seems fine.

Also note that another useful render buffer is the one right before the Irradiance buffer. It's called 'light splatting' and basically shows you the overdraw generated by the light geometry (not just particles, the scene default spotlight goes through there too), this can be useful to spot heavy light-overdraw cases that would otherwise be easy to miss.

(like lots of large dim light particles that would produce a reasonable amount of lighting in the scene, but a huge very unreasonable amount of overdraw, especially for consoles).

Tut02 13.jpg

The light renderer lets you choose between two light materials: one purely diffuse (by default), and one that also renders specular highlights for each light particle:

Tut02 16 2.jpg

The light falloff can be tweaked with the 'LightAttenuationSteepness' parameter.

Higher values produce a softer falloff:

Tut02 17.jpg

Tut02 18.jpg

Animated flame textures

This fire needs some flames. we're going to add some animated textures.

First, create a new layer:

Tut02 19.jpg

In the renderer billboard, set the material to 'AlphaBlend_Additive_Soft', the Diffuse texture to "", and the atlas definition to "BlastPack_Extended.txt".

As in the smoke tutorial, by default, the first sub-texture will be displayed:

Tut02 20.jpg

Looking at the atlas, we want to cycle through sub-textures 0 through 31, which are, in order, the 32 frames of the flame animation.

We already saw in the previous tutorial how to set a random sub-texture index for the smoke, by assigning a random value to the 'TextureID' field, inside the spawn script.

As the animation needs to be updated depending on the particle's life, we've got two options:

  • create a 1-dimensional spline with a 'CParticleEvolver_Field', bind it to the field 'TextureID', and make the spline progress linearly from the values 0 at time 0.0 to 32 at time 1.0
  • create an evolve script that will manually animate the TextureID field depending on the particle's LifeRatio

Both methods are fine, but for the sake of the tutorial, we're going to use the script.
Right-click on the evolvers list, and select 'New Evolver' > 'CParticleEvolver_Script' :

Tut02 21.jpg

By default, as you can see in the script editor, by selecting the script evolver, an empty Eval() function is generated.

Now, within this script we have access to 'LifeRatio', which is of type 'float', and contains the normalized particle age, between 0.0 and 1.0
When the particle spawns, 'LifeRatio' starts at zero. When the particle dies, the LifeRatio equals 1.0

Therefore, if we want to make the TextureID progress linearly from 0 to 31 through the whole particle life, we just need to write:

function void	Eval()
	TextureID = LifeRatio * 32;

By the way, having the smoke on top of the animated flame we're going to tweak makes it a bit hard to see things, so you can temporarily hide the smoke alltogether by unchecking the layer's visibility checkbox (on the right of the layer name):

Tut02 22.jpg

That already makes our sprite animate correctly.
Additionally, we can tweak some other parameters in the spawn script:

The particles spawn at y=0, therefore they're half in the ground, they also disappear a bit too quickly. Let's move them a bit higher and make them last a bit longer, and more randomly to give more variety to the effect.

In the spawn script:

function void	Eval()
	Life = rand(1.8, 2.5);
	Size = 0.5;
	Position = float3(0, 0.25, 0);

Tut02 23.jpg

There are currently quite a lot of flame particles, and it makes it hard to see the animation, so just bring the SpawnCount in the particle spawner back to around 4 per second:

Tut02 24.jpg

Now, let's add a color curve to control the particle's colors. Make sure the alpha stays at zero.

With the AlphaBlend_Additive* materials, this will make the particle additive.
We could use a purely additive material, but, as said in the smoke tutorial, it will batch poorly with the smoke particles, and some sorting problems will appear.

Tut02 25.jpg

Boosting the color curves above 1 will make the sprites strongly emissive, and they'll start glowing, like intense flames. Just make sure you have the 'HDR/Glow' post-FX enabled, in the post-FX dropdown, in the realtime viewport's upper toolbar:

Tut02 26 1.jpg

Just like with the smoke, to avoid the tiling effect, we're going to add a random rotation to our flames, with a CParticleEvolver_Rotation.

Tut02 27.jpg

As the particles currently have a constant size, we can also notice some popping of the full-sized flame at the birth of every particle. even with a smoothly fading-in color curve, it's still noticeable. Just add a size curve to grow the particle smootly after birth:

Tut02 28.jpg

And just a last fix, as the flame texture animation animates the flame disappearing, there is actually no need to fade the flame intensity as the particle approaches death, we can keep full intensity till the end, as this is already encoded in the texture animation:

Tut02 29.jpg

Fire/Smoke integration tweaks

If we now unhide the smoke, we can see it's far from perfect, the flames are too big compared to the smoke, it doesn't appear to smoothly blend-in together.

Tut02 30.jpg

To fix this, we'll just rescale/tweak the smoke color curves so that it looks a bit nicer:

Tut02 31.jpg

Tut02 32.jpg

Procedural wind turbulence

The last thing we'll see in this tutorial is the procedural turbulence sampler, to move the smoke column around like it's in turbulent air.

Right-click in the Samplers node, and select 'New Sampler' > 'CParticleSamplerProceduralTurbulence'.


The new sampler will have a default name of 'Sampler_0'.

Now, if you select the physics evolver, you will notice a 'VelocityFieldSampler' field. just type in the name of the sampler you want to use as the velocity field. in this case, "Sampler_0".

Particles using the physics evolver are affected by windfields depending on their friction parameters, and their mass. With all friction parameters set to 0, the particles aren't going to be affected by anything at all. We're going to use the 'FluidFriction' field for this example, and set it to 0.1 :

/!\ The old "FluidFriction" and "StaticFriction" properties were simplified into a single "Drag" property. Also, FYI, the only working "DragType" right now is "Linear", we might remove this in the future, as we now only support linear drag anyway.

Tut02 34.jpg

If you now select the procedural turbulence sampler, you can start playing around with the parameters, and see the effects in the realtime viewport.

The sampler also creates a debug visualization of its vector field, in the 'ParticleNode Editor' panel.

If you change, for example, the 'strength' parameter to 20, you'll see the smoke trails following curved paths. but the paths are fixed, they don't wiggle around like a real fluid turbulence would.

Tut02 35.jpg

To fix this, you can animate the turbulence sampler, through the 'TimeScale' field. if set to 0, the sampler isn't animated, if set to 1, the animation pattern repeats every second, if set to 0.1, it animates slower and repeats every 10 seconds.

You can increase the 'RandomTimeVariation' parameter to make the repetition less obvious.

Tut02 36.jpg

This gives us the final effect:

Tut02 37.jpg

Previous tutorial : Particle tutorial smoke
Next tutorial : Audio spectrum sampler