Skip to content

Particle System

Utilize this powerful and flexible particle system in your effects to create stunning dynamic visualizations. It allows you to either manually add particles to the system or to create and add particle emitters, which continually spawn particles into the system.

For more information about the particle system, make sure to read the extension SDK documentation as well.

Basic Particle Effect

The following example is the most basic effect with particle system you can create. Notice, how the particle system is created utilizing the effect API.

[EffectExtension("Basic Particle Effect", "Audectra", "0.0.1")]
class BasicParticleEffect : EffectExtensionBase
{
    private readonly IEffectApi _api;
    private readonly IRgbRender _render;

    private readonly IParticleSystem _particleSystem;

    public BasicParticleEffect() { }

    public BasicParticleEffect(IEffectApi effectApi, int width, int height) : base(width, height)
    {
        _api = effectApi;
        _render = _api.CreateRender();
        _particleSystem = _api.CreateParticleSystem();
    }

    public override IRgbRender Render(float dt)
    {
        _render.Clear();
        _particleSystem.Update(dt);
        _particleSystem.Render(_render);

        return _render;
    }
}

The particle effect above includes and renders a particle system. However, there are no particles included yet. Read on for more details on how to get some particles into the system.

Particles

Every particle system needs particles. In this section, we will discuss the configuration options of particles and how to manually add them into the system.

Configuration

Particles have many configurable properties, which will be discussed below.

Position

The position property of a particle corresponds to its starting position in the particle system.

Angle

The angle property defines the direction in degrees, in which the particle is moving, if its speed is greater than zero.

Speed

The speed property defines how fast the particle is moving from its starting position, defined with Position, in the direction, defined with Angle.

Life

The life of a particle is defined in seconds. If the a particles lifespan has been reached, it will disappear from the particle system.

Rotation Axis

The position of the rotation axis for a particle is needed for the tangential or radial acceleration properties.

Radial Acceleration

The radial acceleration of a particle defines the pull (> 0) or push (< 0) force on the particle towards or from its rotation axis.

Tangential Acceleration

The tangential acceleration of a particle defines the clockwise (> 0) or counter-clockwise (< 0) force on the particle around its rotation axis.

Begin Color

The particle color at the beginning of its lifespan.

Begin Size

The particle size at the beginning of its lifespan.

End Color

The particle color at the end of its lifespan.

End Size

The particle size at the end of its lifespan.

Add a Particle

Take a look at the effect source Audectra/v0/Beams.cs, which creates and adds a new particle to the system on every trigger.

[EffectExtension("Beams", "Audectra", "1.3.0")]
class Beams : EffectExtensionBase
{
    // ...

    public override void OnTrigger(uint triggerId, bool risingEdge)
    {
        if (!risingEdge)
            return;

        switch ((TriggerId) triggerId)
        {
            case TriggerId.BeamMeUp:
                var particleConfig = new ParticleConfig
                {
                    Angle = 0,
                    Life = float.MaxValue,
                    Speed = _particleSpeed,
                    Position = new Vector2(0, 0),
                    AxisPosition = new Vector2(0 ,0),
                    BeginSize = _particleSize,
                    EndSize = _particleSize,
                    BeginColor = _color,
                    EndColor = _color
                };

                _particleSystem.AddParticle(particleConfig);
                break;
        }
    }

    // ...
}

Particle Emitter

If you need to periodically spawn new particles into the system, then a particle emitter is exactly what you are looking for.

Configuration

The particle emitter allows you to define ranges for many particle properties, from which it will randomly pick a value on each particle creation. This allows to create more 'natural' particle effects by introducing more randomness.

Tip

Unlike the particle configuration, the particle emitter configuration can be used to configure the particle emitter, even after it has been added to the particle system.

Position

Set the position of the particle emitter in the system.

Emission Rate

The emission rate of a particle emitter defines how many particles it generates per second.

Angle Range

Set a range for the particle moving direction.

Speed Range

Set a range for the particle speed.

Life Range

Set a range for the particle life in seconds.

Rotation Axis

Set the position of the particles rotation axis.

Radial Acceleration Range

Set the range for the particles radial acceleration.

Tangential Acceleration Range

Set the range for the particles tangential acceleration.

Begin Color

The particle color at the beginning of its lifespan.

Begin Size Range

The particle size at the beginning of its lifespan.

End Color

The particle color at the end of its lifespan.

End Size Range

The particle size at the end of its lifespan.

Add a Particle Emitter

Take a look at the effect source Audectra/v0/Fire.cs, which creates and adds multiple particle emitters to the system.

[EffectExtension("Fire", "Audectra", "1.3.0")]
class Fire : EffectExtensionBase
{
    private readonly IEffectApi _api;
    private readonly IRender _render;

    private SKColor _beginColor;
    private readonly IParticleSystem _particleSystem;
    private readonly List<IParticleEmitter> _particleEmitters;

    private const float EmberDistance = 4;

    // ...

    public Fire(IEffectApi effectApi, int width, int height) : base(width, height)
    {
        _api = effectApi;
        _render = _api.CreateRender();
        _particleSystem = _api.CreateParticleSystem();

        _beginColor = new SKColor(128, 64, 16);
        var endColor = new SKColor(64, 64, 64);
        _particleEmitters = new List<IParticleEmitter>();

        int numEmbers = Math.Max((int) (Width / EmberDistance), 1);

        for (int i = 0; i < numEmbers; i++)
        {
            var xPos = Width / (numEmbers - 1f) * i;
            var yPos = Height;

            var emitterConfig = new ParticleEmitterConfig
            {
                Position = new Vector2(xPos, yPos),
                AxisPosition = new Vector2(xPos, yPos),
                EmissionRate = 8,
                Angle = new Range<float>(45, 135),
                Life = 4,
                Speed = 4,
                RadialAcceleration = 0,
                TangentialAcceleration = 0,
                BeginColor = _beginColor,
                EndColor = endColor,
                BeginSize = 4,
                EndSize = 4,
                EnableSizeTransition = true,
                EnableColorTransition = true,
            };

            var emitter = _particleSystem.AddEmitter(emitterConfig);
            _particleEmitters.Add(emitter);
        }
    }

    public override IRgbRender Render(float dt)
    {
        _render.Clear();
        _particleSystem.Update(dt);
        _particleSystem.Render(_render);

        return _render;
    }

    // ...
}