Header menu logo Mibo.Raylib

2D Particles

The particle system renders textured quads in bulk. It is independent of lighting — particles can be lit (LightDraw.litSprite) or unlit (ParticleDraw.particles).

Separation of concerns

Particle rendering is split into two layers:

  1. Simulation — your update function handles velocities, lifetimes, physics
  2. Render — writes Particle2D snapshots, ParticleDraw.particles adds them to the buffer

Particle2D

[<Struct>]
type Particle2D = {
    Position: Vector2      // center position (world or screen)
    Size: Vector2           // width and height
    Rotation: float32       // degrees
    SourceRect: Rectangle   // source rect on the texture
    Color: Color            // tint + alpha
}

Rendering

// Pre-allocate a pool in your model
let particles = Array.zeroCreate<Particle2D> 1024
let mutable particleCount = 0

// Each frame, write active particles into the array, then draw:
buffer
|> ParticleDraw.particles particleTexture particles particleCount 10<RenderLayer>

ParticleDraw.particles adds a single command to the buffer that draws all particles in a loop. All particles share one texture.

Simulation helpers

ParticleSimulation.fadeAndCompact fades particles by reducing alpha and compacts dead ones out of the array:

open Mibo.Elmish.Graphics2D.Lighting

// In your update (e.g., Tick handler):
ParticleSimulation.fadeAndCompact
    particles            // Particle2D array
    &particleCount       // byref — updated after compaction
    60f                  // fade speed (alpha/sec — 60 = fully faded in 1s)
    dt                   // delta time

Particles with alpha ≤ 0 are removed in a single pass. The array is compacted in-place (no allocation).

Performance

See Also

Multiple items
type StructAttribute = inherit Attribute new: unit -> StructAttribute

--------------------
new: unit -> StructAttribute
[<Struct>] type Particle2D = { Position: obj Size: obj Rotation: float32 SourceRect: obj Color: obj }
Multiple items
val float32: value: 'T -> float32 (requires member op_Explicit)

--------------------
type float32 = System.Single

--------------------
type float32<'Measure> = float32
val particles: Particle2D array
module Array from Microsoft.FSharp.Collections
val zeroCreate: count: int -> 'T array
val mutable particleCount: int

Type something to start searching.