Module bevy_hanabi::graph::expr

source ·
Expand description

Expression API

This module contains the low-level Expression API, designed to produce highly customizable modifier behaviors through a code-first API focused on runtime and serialization. For asset editing, the higher-level Node API offers an easier-to-use abstraction built on top of the Expression API.

§Modules and expressions

A particle effect is composed of a series Modifiers decribing how to initialize and update (simulate) the particles of the effect. Choosing which modifier to add to an effect provides the user some limited level of customizing. However modifiers alone cannot provide enough customizing to build visual effects. For this reason, modifier inputs can be further customized with expressions. An expression produces a value which is assigned to the input. That value can be constant, in which case it will be hard-coded into the generated WGSL shader, for performance reasons. Alternatively, that value can vary based on other quantities, like an effect property, a particle attribute, or some built-in simulation variable like the simulation time.

An expression is represented by the Expr enum. Expressions can be combined together to form more complex expression; for example, the Add expression computes the sum between two other expressions. Expr represents a form of abstraction over the actual WGSL shader code, and is generally closely related to the actual expressions of the WGSL language itself.

An expression often refers to other expressions. However, Expr as an enum cannot directly contain other Expr, otherwise the type would become infinitely recursive. Instead, each expression is stored into a Module and indexed by an ExprHandle, a non-zero index referencing the expression inside the module. This indirection avoids the recursion issue. This means all expressions are implicitly associated with a unique module, and care must be taken to not mix exressions from different modules.

Each EffectAsset contains a single Module storing all the Expr used in all its modifiers.

§Kinds of expressions

Expressions can be grouped into various kinds, for the sake of comprehension:

  • Literal expressions represent a constant, which will be hard-coded into the final WGSL shader code. Expressions like 1.42 or vec3<f32>(0.) are literal expressions in WGSL, and are represented by a LiteralExpr.
  • Built-in expressions represent specific built-in values provided by the simulation context. For example, the current simulation time is a built-in expression accessible from the shader code of any visual effect to animate it. A built-in expression is represented by a BuiltInExpr.
  • Attribute expressions represent the value of an attribute of a particle. A typical example is the particle position, represented by Attribute::POSITION, which can be obtained as an expression through an AttributeExpr.
  • Property expressions represent the value of a visual effect property, a quantity assigned by the user on the CPU side and uploaded each frame into the GPU for precise per-frame control over an effect. It’s represented by a PropertyExpr.
  • Unary and binary operations are expressions taking one or two operand expressions and transforming them. A typical example is the Add operator, which takes two operand expressions and produces their sum.

§Building expressions

The fundamental way to build expressions is to directly write them into a Module itself. The Module type contains various methods to create new expressions and immediately write them.

let mut module = Module::default();

// Build and write a literal expression into the module.
let expr = module.lit(3.42);

Due to the code-first nature of the Expression API however, that approach can be very verbose. Instead, users are encouraged to use an ExprWriter, a simple utility to build expressions with a shortened syntax. Once an expression is built, it can be written into the underlying Module. This approach generally makes the code more readable, and is therefore highly encouraged, but is not mandatory.

// Create a writer owning a new Module
let mut w = ExprWriter::new();

// Build a complex expression: max(3.42, properties.my_prop)
let expr = w.lit(3.42).max(w.prop("my_prop"));

// Finalize the expression and write it into the Module. The returned handle can
// be assign to a modifier input.
let handle = expr.expr();

// Finish using the writer and recover the Module with all written expressions
let module = w.finish();

Structs§

  • Expression representing the value of an attribute of a particle.
  • Expression for getting built-in quantities related to the effect system.
  • Expression to cast an expression to another type.
  • Handle of an expression inside a given Module.
  • Expression writer.
  • A literal constant expression like 3.0 or vec3<f32>(1.0, 2.0, 3.0).
  • Container for expressions.
  • Expression representing the value of a property of an effect.
  • Intermediate expression from an ExprWriter.

Enums§

Traits§

  • Evaluation context for transforming expressions into WGSL code.