sealed class Tinman.Engine.Particles.ParticleBuffer

Derived from

Disposable abstract

A particle buffer stores per-particle information and updates particle data in a background thread.

The following steps are necessary to setup and run a particle buffer:

  • Create an instance of IParticleUpdater. This object will be used by the particle buffer to update per-particle data. Often this is a composite object created with IParticleUpdater.Append, to combine existing updater implementations, for example gravity, wind or velocity damping.

  • Choose the capacity of the particle buffer and the update rate of its particles. These values depend on the intended use case (big and slow-moving smoke particles vs. tiny high-speed spark particles) and should be chosen accordingly. For rendering, per-particle data is interpolated from fixed time-step values, so animation smoothness is independent of the update rate.

  • Create an instance of ParticleBuffer, passing the data arrays, the updater and the update rate. The particle buffer processes per-particle data in a background thread and sleeps if there are no particles to process.

  • Periodically call IUpdateableFrameTime.UpdateFrameTime, in order to advance the simulation time for particles. The background processing thread will sleep if no per-particle data needs to be processed.

  • Use CreateBegin to begin creation of particles. For each particle, update the particle data in Data. Once complete, call CreateEnd to submit the initialized particles.

The particles in the buffer are arranged as a ring buffer and a sliding window of active particles is maintained (the active region, see Count): new particles are inserted at the end of the sliding window and dead particles are removed from the beginning. There may be dead particles in the middle, these will be removed when the sliding window moves past them. To actually use the particles in a buffer, perform these steps:

  • Create an instance of IParticleOutput, for example an InstanceOutput object, which generates a 3D model instance for each non-dead particle in the active region.

  • Use IParticleOutput.Prepare to create a snapshot of the data in the particle buffer, which is updated at a fixed rate by a background thread.

  • Use IParticleOutput.Output to generate GPU data for rendering the buffered particles, using time-based interpolation to get smooth animation, even if the particles are updated at a low rate.

  • Render the particles, as explained by the documentation of the IParticleOutput implementation class.

The particle effect framework of an application usually has a small number of particle buffers and a variety of IParticleOutput objects, which produce GPU data for rendering. The visual appearance of a particle may be controlled with these data arrays:

Particle movement is captured by these data arrays:

The Age data array is used by the particle buffer to compute the active region and may also be used to apply variations to particle data, based on the particle age.

Public / Constants


public static readonly attribute Acceleration → (Semantic)

The acceleration vector, in world-units per square second.

Name: 'Acceleration'
Tuple size: 3
Tuple type: TupleType.Float


public static readonly attribute Age → (Semantic)

The particle age, in seconds.

Name: 'Age'
Tuple size: 2
Tuple type: TupleType.Float

The current age (see TupleComponent.X) will be greater than or equal to zero for all particles in the active region (see Count) and will be 0 for all other particles.

The maximum age (see TupleComponent.Y) will be greater than zero for all particles in the active region (see Count) and will be 0 for all other particles.


public static readonly attribute Color → (Semantic)

The overall particle color, given as 32-bit ARGB sRGB color value with alpha (see Colors.Encode_A8R8G8B8).

Name: 'Color'
Tuple size: 1
Tuple type: TupleType.Int


public static readonly attribute GeometryId → (Semantic)

The geometry identifier of the particle.

Name: 'GeometryId'
Tuple size: 1
Tuple type: TupleType.Int


public static readonly attribute Intensity → (Semantic)

The high-dynamic range scale to apply to the overall particle color.

Name: 'Intensity'
Tuple size: 1
Tuple type: TupleType.Float


public static readonly attribute Orientation → (Semantic)

The orientation quaternion (unit-length) of the particle.

Name: 'Orientation'
Tuple size: 4
Tuple type: TupleType.Float

See also



public static readonly attribute Scale → (Semantic)

The current particle scale factor.

Name: 'Scale'
Tuple size: 1
Tuple type: TupleType.Float


public static readonly attribute Size → (Semantic)

The overall particle size, where 1 represents the original particle size.

Name: 'Size'
Tuple size: 1
Tuple type: TupleType.Float


public static readonly attribute VelocityAngular → (Semantic)

The angular velocity vector, in radians per second.

Name: 'VelocityAngular'
Tuple size: 3
Tuple type: TupleType.Float


public static readonly attribute VelocityLinear → (Semantic)

The linear velocity vector, in world-units per second.

Name: 'VelocityLinear'
Tuple size: 3
Tuple type: TupleType.Float

Public / Constructors


public static method Builder → ()

Builds a new instance of ParticleBuffer.

Public / Methods


public method CreateBegin → (2)

count in : int32

The number of particles for which to request creation.

recycle opt : bool = true

If there are not enough inactive particles available to honour count in, forcibly kill alive particles and recycle them in order to satisfy the requested count?

returns → Vec2I

The index range of the particles to create:
Vec2I.X : index of first particle
Vec2I.Y : number of particles that must be created
The particle index will be within [0..ICapacity.Capacity-1] and the particle count will be within [0..ICapacity.Capacity]. The Next method may be used to run through subsequent particle indices.

Begins the creation of new particles.

The initial data of the newly created particle is undefined and must be specified by the caller by updating Data, before calling the CreateEnd method.


public method CreateEnd → ()

Finishes the pending creation of new particles.


public method Next → (1)

index in : int32

Index of current particle.

returns → int32

The next particle.

Returns the next particle, wrapping around if necessary.


public method SnapshotBegin → (1)

active out : RangeI

Output for the active region in the particle buffer. Both RangeI.Start and RangeI.End must be wrapped around at ICapacity.Capacity, in order to get the actual buffer range. The unwrapped region may be used to uniquely identity a snapshot.

returns → float64

The accumulated simulation time of the snapshot, in seconds.

Acquires a snapshot of the current particle simulation.

The background thread will be inactive when this method returns.


public method SnapshotEnd → ()

Releases the current particle simulation snapshot.

The background thread becomes active when this method returns.

Public / Attributes


public attribute Count → (get)

value : int32

The number of active particles.

Returns the number of particles in the active region.


public attribute Data → (get)

value : VertexArrays

The per-particle data arrays.

Returns the per-particle data arrays.


public attribute Time → (get)

value : float64

The accumulated simulation time, in seconds.

Returns the accumulated simulation time that has been provided via IUpdateableFrameTime.UpdateFrameTime.


public attribute TimeCreate → (get)

value : float64

The effective simulation time for particle creation, in seconds.

Returns the effective simulation time that will be used when creating new particles.