Expand description
🎆 Hanabi – a GPU particle system plugin for the Bevy game engine.
The 🎆 Hanabi particle system is a GPU-based particle system integrated with the built-in Bevy renderer. It allows creating complex visual effects with millions of particles simulated in real time, by leveraging the power of compute shaders and offloading most of the work of particle simulating to the GPU.
The library supports the wasm
target (WebAssembly) via the WebGPU renderer
only. Compute shaders are not available via the legacy WebGL2 renderer.
See Bevy’s own WebGL2 and WebGPU
section of the examples README for more information on how to run Wasm
builds with WebGPU.
§2D vs. 3D
🎆 Hanabi integrates both with the 2D and the 3D core pipelines of Bevy. The
2D pipeline integration is controlled by the 2d
cargo feature, while the
3D pipeline integration is controlled by the 3d
cargo feature. Both
features are enabled by default for convenience. As an optimization, users
can disable default features and re-enable only one of the two modes. At
least one of the 2d
or 3d
features must be enabled.
# Example: enable only 3D integration
bevy_hanabi = { version = "0.15", default-features = false, features = ["3d"] }
§Example
Add the 🎆 Hanabi plugin to your app:
use bevy_hanabi::prelude::*;
App::default()
.add_plugins(DefaultPlugins)
.add_plugins(HanabiPlugin)
.run();
Create an EffectAsset
describing a visual effect:
fn setup(mut effects: ResMut<Assets<EffectAsset>>) {
// Define a color gradient from red to transparent black
let mut gradient = Gradient::new();
gradient.add_key(0.0, Vec4::new(1., 0., 0., 1.));
gradient.add_key(1.0, Vec4::ZERO);
// Create a new expression module
let mut module = Module::default();
// On spawn, randomly initialize the position of the particle
// to be over the surface of a sphere of radius 2 units.
let init_pos = SetPositionSphereModifier {
center: module.lit(Vec3::ZERO),
radius: module.lit(2.),
dimension: ShapeDimension::Surface,
};
// Also initialize a radial initial velocity to 6 units/sec
// away from the (same) sphere center.
let init_vel = SetVelocitySphereModifier {
center: module.lit(Vec3::ZERO),
speed: module.lit(6.),
};
// Initialize the total lifetime of the particle, that is
// the time for which it's simulated and rendered. This modifier
// is almost always required, otherwise the particles will stay
// alive forever, and new particles can't be spawned instead.
let lifetime = module.lit(10.); // literal value "10.0"
let init_lifetime = SetAttributeModifier::new(Attribute::LIFETIME, lifetime);
// Every frame, add a gravity-like acceleration downward
let accel = module.lit(Vec3::new(0., -3., 0.));
let update_accel = AccelModifier::new(accel);
// Create the effect asset
let effect = EffectAsset::new(
// Maximum number of particles alive at a time
32768,
// Spawn at a rate of 5 particles per second
SpawnerSettings::rate(5.0.into()),
// Move the expression module into the asset
module,
)
.with_name("MyEffect")
.init(init_pos)
.init(init_vel)
.init(init_lifetime)
.update(update_accel)
// Render the particles with a color gradient over their
// lifetime. This maps the gradient key 0 to the particle spawn
// time, and the gradient key 1 to the particle death (10s).
.render(ColorOverLifetimeModifier {
gradient,
blend: ColorBlendMode::Overwrite,
mask: ColorBlendMask::RGBA,
});
// Insert into the asset system
let effect_asset = effects.add(effect);
}
Then add an instance of that effect to an entity by spawning a
ParticleEffect
component referencing the asset.
commands.spawn((
ParticleEffect::new(effect_asset),
Transform::from_translation(Vec3::Y),
));
§Workflow
Authoring and using a particle effect follows this workflow:
- Create an
EffectAsset
representing the definition of the particle effect. This asset is a proper BevyAsset
, expected to be authored in advance, serialized, and shipped with your application. Creating anEffectAsset
at runtime while the application is running is also supported, though. In any case however, the asset doesn’t do anything by itself. - At runtime, when the application is running, create an actual particle
effect instance by spawning a
ParticleEffect
component. The component references theEffectAsset
via itshandle
field. Multiple instances can reference the same asset at the same time, and some changes to the asset are reflected to its instances, although not all changes are supported. In general, avoid changing anEffectAsset
while it’s in use by one or moreParticleEffect
. - If using properties, spawn an
EffectProperties
component on the same entity. Then update properties through that component at any time while the effect is active. This allows some moderate CPU-side control over the simulation and rendering of the effect, without having to destroy the effect and re-create a new one. - If using textures, spawn an
EffectMaterial
component to define which texture is bound to which slot in the effect. AnEffectAsset
only defines “slots” of textures, not the actual assets bound to those slots. This way, you can reuse the same effect asset multiple times with different textures, like you’d do with a regular rendering mesh. - For advanced VFX composed of multiple hierarchical effects, where two or
more effects are connected to each other in a parent-child relationship,
spawn an
EffectParent
on any child effect instance to specify its parent instance. See also theEmitSpawnEventModifier
.
The EffectAsset
is intended to be the serialized effect format, which
authors can save to disk and ship with their application. At this time
however serialization and deserialization is still a work in progress. In
particular, serialization and deserialization of all
modifiers is currently not supported on wasm
target.
Re-exports§
pub use attributes::*;
pub use graph::*;
pub use modifier::*;
pub use properties::*;
Modules§
- attributes
- Effect attributes, like the position or velocity of a particle.
- graph
- Effect graph and language definition, including expressions.
- modifier
- Building blocks to create a visual effect.
- prelude
- properties
- Effect properties.
Structs§
- Compiled
Particle Effect - Compiled data for a
ParticleEffect
. - Debug
Settings - Debugging settings.
- Default
Mesh - Default particle mesh, if not otherwise specified in
EffectAsset::mesh
. - Effect
Asset - Asset describing a visual effect.
- Effect
Material - Material for an effect instance.
- Effect
Parent - Component defining the parent effect of the current effect.
- Effect
Simulation - The effect simulation clock.
- Effect
Spawner - Runtime state machine for CPU particle spawning.
- Effect
Visibility Class - The
VisibilityClass
used for all particle effects. - Gradient
- A gradient curve made of keypoints and associated values.
- Gradient
Key - A single key point for a
Gradient
. - Hanabi
Plugin - Plugin to add systems related to Hanabi.
- Layout
Flags - Effect flags.
- Particle
Effect - Particle-based visual effect instance.
- Property
Value - Value a user wants to assign to a property with
EffectProperties::set()
before the instance had a chance to inspect its underlying asset and check the asset’s defined properties. - Random
- An RNG resource
- Shader
Cache - Cache of baked shaders variants.
- Spawner
Settings - Settings for an
EffectSpawner
. - Texture
Layout - Texture layout.
- Texture
Slot - Texture slot of a
Module
.
Enums§
- Alpha
Mode - Alpha mode for rendering an effect.
- CpuValue
- A constant or random value evaluated on CPU.
- Effect
Systems - Labels for the Hanabi systems.
- Motion
Integration - Type of motion integration applied to the particles of a system.
- Shader
Generate Error - Error resulting from the generating of the WGSL shader code of an
EffectAsset
. - Simulation
Condition - Simulation condition for an effect.
- Simulation
Space - Simulation space for the particles of an effect.
Traits§
- Effect
Simulation Time - All methods for the
Time<EffectSimulation>
clock. - ToWgsl
String - Extension trait to convert an object to WGSL code.
Functions§
- tick_
spawners - Tick all the
EffectSpawner
components.