Crate bevy_hanabi
source ·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.
Note: This library makes heavy use of compute shaders to offload work to
the GPU in a performant way. Support for compute shaders on the wasm
target (WebAssembly) via WebGPU is only available in Bevy in general since
the Bevy v0.11, and is not yet available in this library.
See #41 for details on
progress.
§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.
# Example: enable only 3D integration
bevy_hanabi = { version = "0.12", 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::splat(0.));
// 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(0.05),
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 won't show.
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
vec![32768],
// Spawn at a rate of 5 particles per second
Spawner::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 });
// 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. The simplest way is
to use the ParticleEffectBundle
to ensure all required components are
spawned together.
commands.spawn(ParticleEffectBundle {
effect: ParticleEffect::new(effect_asset),
transform: Transform::from_translation(Vec3::Y),
..Default::default()
});
§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 (or use theParticleEffectBundle
for simplicity). 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
. - Also spawn an
EffectProperties
component on the same entity. This is required even if the effect doesn’t use properties. See properties for more details. - If actually using properties, update them through the
EffectProperties
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.
Re-exports§
pub use attributes::*;
pub use graph::*;
pub use modifier::*;
pub use properties::*;
Modules§
- Effect attributes, like the position or velocity of a particle.
- Effect graph and language definition.
- Building blocks to create a visual effect.
- Effect properties.
Structs§
- Compiled data for a
ParticleEffect
. - Asset describing a visual effect.
- The effect simulation clock.
- Runtime component maintaining the state of the spawner for an effect.
- A gradient curve made of keypoints and associated values.
- A single key point for a
Gradient
. - Plugin to add systems related to Hanabi.
- Effect flags.
- Visual effect made of particles.
- A component bundle for a particle effect.
- 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. - An RNG resource
- Cache of baked shaders variants.
- Spawner defining how new particles are emitted.
Enums§
- Alpha mode for rendering an effect.
- A constant or random value evaluated on CPU.
- Labels for the Hanabi systems.
- Type of motion integration applied to the particles of a system.
- Simulation condition for an effect.
- Simulation space for the particles of an effect.
Traits§
- All methods for the
Time<EffectSimulation>
clock. - Extension trait to convert an object to WGSL code.
Functions§
- Tick all the
EffectSpawner
components of the simulatedParticleEffect
components.