Are you happy with your logging solution? Would you help us out by taking a 30-second survey? Click here


Particle system that's both calculated and rendered on the GPU using the Metal framework

Subscribe to updates I use ParticleLab

Statistics on ParticleLab

Number of watchers on Github 417
Number of open issues 3
Average time to close an issue 16 days
Main language Swift
Average time to merge a PR less than a minute
Open pull requests 2+
Closed pull requests 3+
Last commit over 3 years ago
Repo Created almost 5 years ago
Repo Last Updated over 1 year ago
Size 17 MB
Organization / Authorflexmonkey
Latest ReleaseCAMetalLayer
Page Updated
Do you use ParticleLab? Leave a review!
View open issues (3)
View ParticleLab activity
View on github
Fresh, new opensource launches 🚀🚀🚀
Trendy new open source projects in your inbox! View examples

Subscribe to our mailing list

Evaluating ParticleLab for your project? Score Explanation
Commits Score (?)
Issues & PR Score (?)

ParticleLab - High Performance Particles in Swift and Metal

Particle system that's both calculated and rendered on the GPU using the Metal framework

This is the most highly optimised version of my Swift and Metal particles system; managing over 40 fps with four million particles and four gravity wells. It manages this by rendering to a MetalKit MTKView rather than converting a texture to a UIImage and by passing in four particle definitions per step with a float4x4 rather than a particle struct.

You can read about these recent changes at my blog:

  • A First Look at Metal for OS X:
  • CAMetalLayer work:
  • Use of float4x4:

This branch wraps up all the Metal code into one class so that it's easily implemented in other projects. To create a new particle system object, instantiate an instance of ParticleLab specifying the dimensions and total number of particles (half, one, two or four million):

particleLab = ParticleLab(width: 1024, height: 768, numParticles: ParticleCount.TwoMillion)

...and when ready, add it as a sublayer to your view:


The class has four gravity wells with propeties such as position, mass and spin. These are set with the setGravityWellProperties method:

particleLab.setGravityWellProperties(gravityWell: .One, normalisedPositionX: 0.3, normalisedPositionY: 0.3, mass: 11, spin: -4)

particleLab.setGravityWellProperties(gravityWell: .Two, normalisedPositionX: 0.7, normalisedPositionY: 0.3, mass: 7, spin: 3)

particleLab.setGravityWellProperties(gravityWell: .Three, normalisedPositionX: 0.3, normalisedPositionY: 0.7, mass: 7, spin: 3)

particleLab.setGravityWellProperties(gravityWell: .Four, normalisedPositionX: 0.7, normalisedPositionY: 0.7, mass: 11, spin: -4)

Classes can implement ParticleLabDelegate interface which includes particleLabDidUpdate. This method is invoked with each particle step and can be used, for example, for updating the position of gravity wells.

ParticleLab Features in Detail

Setting Gravity Well Properties

ParticleLab supports up to four gravity wells that have properties for position, mass and spin. These properties are set through the setGravityWellProperties() method that either accepts a GravityWell enum or an index (0 through 3):

particleLab.setGravityWellProperties(gravityWell: .One, normalisedPositionX: 0.3, normalisedPositionY: 0.3, mass: 11, spin: -4)

particleLab.setGravityWellProperties(gravityWellIndex: 0, normalisedPositionX: 0.3, normalisedPositionY: 0.3, mass: 11, spin: -4)

Gravity wells can be cleared so that their mass and spin are set to zero and they have no effect on the particle field:


ParticleLab can also return the normalised position of any gravity well:

getGravityWellNormalisedPosition(#gravityWell: GravityWell) -> (x: Float, y: Float)

The positions of each gravity well can be displayed by setting the value of showGravityWellPositions to true

Setting Particle Properties and Behaviours

Particles are distributed across three classes which have slightly different masses. The particleColor property sets the base color and the other two particles colors use variations of it. For example, if particleColor is set to 0xFFAA00, the other two classes are colored 0x00FFAA and 0xAA00FF.

The dragFactor property defines how paricles decelerate. A value of one implies no deceleratation while a value of zero stops particles immediately. Typical values are between 0.8 and 1.0.

respawnOutOfBoundsParticles respawns particles to the centre of the screen once they escape the bounds of the simulation. Respawned particles radiate outwards from the centre.

The particle field can be reset by resetParticles(). This accepts a Boolean argument indicating whether the particles should appear at the edges of the simulation (default, true) or throughout the entire simualtion (false).


The ParticleLabDelegate protocol contains two methods.

  • particleLabDidUpdate() is fired with each update
  • particleLabMetalUnavailable is invoked if the target device doesn't support Metal
ParticleLab open issues Ask a question     (View All Issues)
  • over 4 years Black screen on iPad Mini Retina 8.3 (12F69) with Xcode 6.3.2
ParticleLab open pull requests (View All Pulls)
  • Create .gitignore
  • Migrate to Swift 3
ParticleLab list of languages used
ParticleLab latest release notes
CAMetalLayer CAMetalLayer

Final version using CAMetalLayer before migrating to MetalKit

release/1.0 Version 1.0

Submitted to App Store!

Other projects in Swift