Your own particle system with simulation nodes

The Digital Production logo has been through a lot recently. It was thrown in Houdini with a wet towel and turned to earth in Tyflow. And now it is set on fire in Blender – where will it end?

There are features in Blender that users have been waiting decades for. Until now, these have included a new particle system developed from scratch. In Blender 3.6, an alternative to the outdated, conventional particles is now finally available: The “Simulation Area” in the Geometry Nodes. As a side effect, not only particles can be simulated, but also cloth, soft bodies, etc. However, you still have to create the simulation manually from scratch. And that’s what we’re going to do in this article using a particle system as an example.

Burn, logo, burn!

As a concrete example, an object should burst into flames, because the fire simulation in Blender also has its quirks, so we use an old-school particle simulation for a stylised fire effect. The Digital Production logo serves as an example object, but you can use any other 3D object.

What actually is a Simulation in Blender?

In Blender, all processes whose state in a frame depends on the state in the previous frame are a simulation.
This classically includes particles, Cloth, Soft Bodies, Rigid Bodies, Fire, Water, Smoke and the Blender speciality “Dynamic Paint”. On the other hand, there are tools such as the modifiers from the “Modify”, “Generate” and “Deform” categories as well as
geometry Nodes, where each frame can be each frame is independent of the others.

Simulation Zone

In Blender 3.6, you can now set up a so-called “Simulation Zone” in these geometry nodes zone”, which is the area in which the simulations run. You can visualise this as follows. At the input of the simulation zone you can feed in data. These are read out once and remain in the simulation zone from then on Simulation zone. Processed data can be output. These are then fed back into the simulation in the next frame via sent back to the simulation zone via the input and can be further processed there. This can be the position of a particle, but also its size or any other property size or any other property, which can be accessed with Geometry Nodes. Changing the size with the lifetime of a particle, for example, was previously not possible at all. Thanks to geometry nodes, we now have almost complete freedom when it comes to the structure of particle systems. However, this is still accompanied by the requirement that you have to create everything yourself. On the geometry node side, Blender 3.6 only offers the simulation zone and the associated features such as baking, but not yet any high-level tools such as emitters or force fields. These will probably be delivered in the future as nodegroup assets similar to the hair assets that have found their way into Blender 3.5. Until then, however, manual work is the order of the day.

Create a new scene and leave the default cube


Leave the default cube alive for a change. It should act as a container for our particle system. It is best to give it a suitable name such as “Particle Nodes Container” using the shortcut F2. Then switch to the Geometry Nodes workspace and click on “New” to create a new node tree. Assign a suitable name here too, such as “Fire Particle System”.

My first particle system: the “Hello World” of particle systems, so to speak. Particles are distributed on the faces of the cube, which fly upwards in the following frames thanks to the offset in the set position node.

Enter the Zone

Use “Shift A – Simulation – Simulation Zone” to create a sub-zone in which the simulation will take place later. This is highlighted in burgundy and has its own input and output. If nodes are interposed, the highlighted area becomes larger. Nodes that are located within it have access to simulation data and are themselves part of the Simulation. Nodes from outside can be connected to the nodes in the zone, but then have no access to the simulation themselves, which will prove to be practical later on.

Distribute points on surfaces

A particle system is based on points, so our first task is to add them. For now, the geometry of the default cube will serve as the emitter. Add a “Point – Distribute Points on Faces” node and place it between the geometry inputs and outputs of the simulation zone. Nothing should happen yet, however, as the simulation zone is not yet connected to anything. Drag the geometry output of the simulation output node to the geometry input of the group output node and the geometry input of the group input node to the input of the simulation input node with the same name. If the playhead in the timeline is set to frame 1, points should now appear in the viewport.

Set in motion

However, the dots are not yet moving, i.e. we have a particle system but not yet a simulation. A node that changes or updates the position of the particles in each frame is still missing. Add a “Geometry – Write – Set Position” node and place it between the Points output of the Distribute Points on Faces node and the Geometry input of the Simulation Output node. Under “Offset”, set the value for Z to 0.1. If you now start the animation from frame 1, the particles move upwards at a constant speed, as 0.1 is added to the Z position in each frame.

My better particle system: With just a few nodes, we were able to create a particle system with animatable emission.

My first Particle system

Congratulations, you have just created your first own particle system with the Blender Simulation Nodes. It consists of an emitter that distributes particles on the surfaces of the input object. These particles are shifted upwards by a constant factor in each frame. The structure corresponds to a legacy blender particle system in which the start and end of the particle emission fall on the same frame.

Influence from outside

Another typical way of emitting particles is recurring emission over several frames, a kind of inflow object. This is also the default setting of the legacy particle system. In the simulation nodes, we have to regularly add new particles from outside the simulation area. This requires an additional object. At this point, the previous cube becomes the container of the particle system and another object takes on the role of the emitter.

In our example, we use the DP logo, but you can use any mesh objects. Add an “Input – Scene – Object Info” node. This has an orange input socket. Connect it to the empty socket of the group input node. An input field for objects now appears in the modifier. You can name it by opening the sidebar in the Node Editor with the N key and entering a suitable name such as “Emitter Object” in the Group tab under “Inputs”. You can even define a tooltip here.

Degraded to a mere container

Switch the object info node to “Relative” so that the points also appear in the correct position later if you move, scale or rotate the object. Then connect the geometry output to the mesh input of the Distribute Points on Faces node and disconnect the geometry input of the Simulation Input node. This cuts the connection to the original geometry of the cube; it is now just a container for the simulation.

Union

Add an object of your choice to the scene and select it in the Geometry Nodes modifier of the container. If you now play the animation from frame one using the space bar, particles will only appear once again. In order for the emitter to emit particles permanently, the newly added points must be merged with the existing ones in each step.
Add a “Geometry – Join Geometry” node and place it on the connection between “Distribute Points on Face” and “Set Position”. The Join Geometry node has a slightly elongated input socket. This illustration is intended to indicate that any number of nodes can be plugged in here. Connect the geometry output of the simulation input node to it.

Randomness at any time

If you now start the simulation from frame one, you will see a stream of particles from the emitter. But they still look like threads because they are generated from exactly the same position on the surface of the object at each frame. However, we need a different distribution in each frame so that it looks like particles are being emitted from the entire surface. Add a node “Input – Scene – Scene Time” and connect the frame output to the seed input of the Distribute Points on Faces node. Also connect the Density input of the node to the empty socket of the Group Input node in order to be able to control the emission density from outside.

Animated particle emission

If you now play the animation, you will not only see a particle beam flying away from your object, you can even animate how many particles the emitter generates per frame. This was previously not so easy to do with the legacy particle system in Blender. This is where the strength of Simulation Nodes comes into play, because you no longer have to worry about such limitations.

For life

Another feature of particle systems is the option of giving each particle a lifetime and reading out its current age. In the simulation nodes, we achieve this by setting an “age” attribute for each point at birth, which is then incremented by one in each frame. Add a node “Attribute – Capture Attribute” between Distribute Points on Faces and Join Geometry. A float with the value 0.0 is now assigned to each point when it is created. Connect the attribute output to the empty input socket of the simulation output node. A corresponding output now appears at the simulation input node.

Marry

Just as with the Join Geometry node for the points, we also need to find a way to “marry” the age of the existing particles with the newly added ones. Add a “Utilities – Math – Math” node. This is already set to the correct “Add” operation by default. Now all particles have the attribute and it is looped through the simulation. However, we are not yet counting up. Duplicate the add node and place it between the existing add node and the simulation output node and set the value in the lower input to 1.0. Now one is added to the age with each frame.

Age and lifetime: A new lifetime factor has been added to the particle system. If this is exceeded, the corresponding points are removed from the simulation. A corresponding output attribute has been added so that the shading can later be influenced based on the age of the particles.

Age vs. lifetime

Age has not yet had any effect. We can use it to make particles die or disappear after a certain time in frames. Duplicate one of the add nodes and place it in a free area in the simulation zone. Connect the upper input to the second add node and change the The operation to “Greater Than”. Add then use “Input – Group – Group Input” to add another Group Input node and connect the threshold input of the Greater Than node to the free socket of the Socket of the group input node. Name the new parameter “Lifetime”, a default value of 50.0 makes sense here. Add a “Geometry – Operations – Delete Geometry” node and place it between the Geometry output of the Set Position node and the Geometry input of the Simulation Output node. Connect the Selection input to the the Value output of the Greater Than Node. From now on, all particles that are older than their lifetime will be removed from the simulation. If you play the animation now, the particles will disappear again from frame 50.

Normalisation

We can also use the age of the points as an output attribute so that we can later colour the particles differently in Cycles depending on their age. As Cycles likes to be fed with values between 0.0 and 1.0, we should normalise it to this value range beforehand. First connect the attribute output of the simulation output node to the free socket of the group output node. If you now open the Ouput Attributes panel in the modifier, you will see an empty field. Here you can later give the attribute a name so that you can access it in the shader, e.g. “age”. It will then also appear as a separate column in the Spreadsheet Editor. You can change the labelling of the field and the tooltip again in the Group tab of the sidebar of the Node Editor, for example to “Age”.

Force fields

The second component we would add to the legacy particle system would be force fields to control the movement of the particles. In the simulation nodes, this is done within the simulation zone via vectors that control the offset of the Set Position node. In our case these would be two components. A kind of wind that blows the particles in a desired direction and a field for swirling. We can simplify the wind extremely by assuming a constant movement in one direction. If we add a Z component, we have also integrated the buoyancy.

The finished particle system: Once the noise texture has been integrated as a turbulence field and the material has been set, the particle system is complete.

Drift

Connect the offset input of the Set Position node to the free socket of the Group Input node and name the newly created input “Wind Force”. A value of 0.05, 0.01 and 0.025 causes the particles to drift gently and slightly backwards.

Swirl

We need a second force to swirl the particles. We can extract this from a noise texture. This is because the RGB colours of the texture can also be interpreted as XYZ values of a vector. These must be merged with the previous forces, again using maths. Add a “Utilities – Vector – Vector Math” node and place it between the wind force socket of the Group Input node and the offset input of the Set Position node. Click on the lower, free vector input of the add node and drag the mouse to a free position. There should be a plus symbol next to the mouse cursor. If you now release the mouse, a search field will appear. Enter “Noise” there and select “Noise Texture – Colour” from the search results.

Adjustments

A noise texture appears whose colour output is directly connected to the vector input of the add node. If you now play the animation, the particles shoot off at a diagonal. This is because the noise texture only outputs positive values between 0.0 and 1.0 for each channel. The result should be colours, and their channel values are defined in Blender as a Range between 0.0 and 1.0.

Negative

However, the particles should move in all directions, even in the opposite direction to an axis, i.e. in a negative direction. To achieve this, we have to subtract 0.5 from all channels, then the range is between -0.5 and 0.5. Duplicate the Vector Math node, place it between the colour output of the Noise Texture node and the existing Vector Math node, which is currently set to “Add”, and set the operator of the new node to “Subtract”. Enter 0.5, 0.5 and 0.5 in the lower vector field.

Buzz

If you now play the animation, you will see quite a hustle and bustle. The turbulence caused by the noise texture is still much too strong. Duplicate a Vector Math node again, place it between Subtract and Add and set the operation to “Scale”. Set the lower input to 0.2 and connect it to the free socket of the to the free socket of the Group Input Node. Name the new input parameter “Turbulence Strength” and view the animation. Set the Lifetime to 100 and the particles will now be swirled around by the noise texture.

Control

How coarse or fine the turbulence is can be controlled via the scale input of the noise texture node. Set it to 1.0 and also connect it to the Group Input node and name the parameter “Turbulence Scale”. If you now play the animation, the particles will flow as if you had added a turbulence force field to a legacy particle system and set the flow value to 1.0. However, this stream-like flow is not quite the way fire moves. The flames flicker and constantly change direction.

The fourth dimension

To simulate this effect with the Noise Texture, switch the drop-down in the Noise Texture to “4D”. A new input “W” has now been added. This can be used to permanently change the noise texture. In other programmes, the parameter is called “Evolution”, which really is a good name. To animate this, you do not need to set any keyframes. Instead, connect it to the Seconds output of the Scene Time node and the particles will wobble and flicker when the animation is played.

Set material

Before you can move on to shading, you need to give the particles a material. To do this, add a “Material – Set Material” node between the geometry output of the simulation output node and the geometry input of the group output node. Select an existing material from the drop-down menu and edit the name and the shader in the next step.

Rendering in Cycles: The points generated by the simulation nodes cannot yet be displayed with Eevee, so we use Cycles as the render engine. The ‘age’ attribute is used for colouring, the name of which we have assigned in the modifier and entered exactly as it is in the attribute node.

Rendering in Cycles

To render the particles, we need the Cycles render engine, as Eevee cannot yet display the points. In the Render tab of the Properties Editor, change the render engine to Cycles and switch to the Shading Workspace. Switch on the Render Preview in the viewport; the particles now appear as small spheres. In the Shader Editor, select the same material in the material drop-down that you have also assigned in the geometry nodes. Now you can also change the name, e.g. to “Particle Material”.

Cycles should recognise them by their name

Add a new node “Input – Attribute” and enter the exact name you have given to the Age attribute in the “Name” field and connect the Fac output to the Base Colour input of the Principled BSDF node. The particles are now coloured in a gradient from black to white, depending on their age. The perfect input for a colour ramp.

Ramp

Insert a “Converter – Colour Ramp” node between Fac and Base Color. Set another stop by pressing the plus icon of the node and set the stop on the far left to a light, desaturated orange. Then set the value for “Value” in the colour wheel to 5.0. Now the particles reflect more light than hits them. A nice effect, which is not physically correct at all, but gives a little more detail than when using emission. Set the second stop to a rich red with a value of 2.0 and the last stop to pure black. Also set the interpolation in the dropdown in the top right-hand corner of the node to “Ease”.

Fadeout

The spheres are now coloured, but it would be nice if they fade out as if the flames were burning out or dissipating like smoke. Connect the Fac output of the Attribute node to the Alpha input of the Principled BSDF node. Now it looks as if the logo is smoking at the beginning and the smoke is turning into fire. For the fire to finally fade out, we need another colour ramp. Set three stops again and the interpolation to “Ease”. The centre stop is given a pure white and the right-hand stop a pure black. The left stop is given a value of 0.1 so that the particles on the emitter are still slightly visible and virtually envelop it.

Artefacts

Black artefacts should now have appeared in the tips of the flames, depending on how many particles you use. The black spots are caused by the fact that Cycles only visits a certain number of surfaces, the so-called bounces. And every time a ray passes through one of the spheres, that’s two transparent bounces. Set the number of transparent bounces in the Light Paths panel of the Render Properties to 256. Now the flame tongues fade out cleanly.

Light and shadow

As the particles in our setup are dependent on light from outside to glow, it is worth loading an HDRI texture into the world. You can achieve the black background by opening the “Ray Visibility” panel in the world properties and unchecking “Camera” and “Glossy”. The latter is a small preparatory step for the next step.

Laying the floor

Add a tarp to the scene and scale it by a factor of 50. Then add a new material and set the value for “Metallic” in the Principled BSDF node to 1.0. You can adjust the strength of the reflection by making the base colour lighter or darker. For an exact replication of the result, set the value of “Value” in the colour selection of the base colour to 0.5. Next, delete the light source that is still present and, if necessary, make the material of the emitter object darker so that it is clearly recognisable in contrast to the light “smoke”.

Bake a cake

After placing the camera, it’s time to render. You can render both a still image and an animation. It would be practical if the simulation data could be saved so that you don’t have to simulate again and again. This process is called “Baking” and can be found for the simulation nodes in the Physics tab of the Properties Editor. Open the Simulation Nodes panel there and click on “Bake”. All frames in the timeline are now simulated and saved. A new simulation is not necessary.

Outlook

This article was intended to provide an overview of how particle systems in the new are structured in the new simulation nodes. From this basis you can proceed further. You could also change the radius of the particles with age. A feature that is also not so easily possible with the legacy particle system. Or you can modify it so that the time-dependent calculations always take place in seconds instead of frames, making your system independent of the project’s frame rate. In order to make the fire flicker even better, you could also
also modulate the emission with a safely time-varying noise texture. Even more: you can make the result more realistic by giving the particles a very slight initial velocity along the normal of the emission object.

Conclusion

With the new simulation nodes in Blender 3.6, particle systems can be created whose thickness exceeds that of the existing legacy particle system. Thanks to the power of the geometry nodes, there is enormous potential ahead of you, but it still needs to be realised. Because there are still no high-level nodes, you have to click together things like an emitter or a force field yourself. It is to be expected that there will be numerous node groups and assets in the future, both from the developers themselves and from the community.