Skip to content

TrailsEffect

Source: TrailsEffect.h

TrailsEffect

class TrailsEffect
src/light/effects/TrailsEffect.h:33

Inherits: EffectBase

Effect: bright dots thrown into a flowing medium, leaving tails the flow carries and bends.

TrailsEffect card TrailsEffect controls

An emitter draws bright points, [draw::advect16] carries the plane, [draw::decay16] dims it. Run every frame, that loop is what a trail is. The tail is last frame's dots moved and dimmed, so the flow's shape is visible in it.

Prior art: 4wheeljive's FlowFields from a Stefan Petrick concept, and Stam's backward advection.

Public Attributes

uint8_t speed = 40 : How fast the medium moves, and with it every tail.

uint8_t dots = 3 : Emitter density: the count scales with the grid.

uint8_t scale = 30 : The flow field's cell size. Low gives broad sweeps, high gives eddies.

uint8_t persistence = 90 : How long a tail survives, as a half-life.

uint8_t breathe = 40 : How much the flow's strength rises and falls.

Public Methods

virtual inline const char * tags() const override : Catalog tags: this effect is the power-function showcase.

virtual inline Dim dimensions() const override : Volumetric, and each slice gets its own flow.

virtual inline void defineControls() override : Publish the flow, the emitter density and the tail's half-life.

virtual inline void prepare() override : Size the wide plane and its spare, and clear both when the grid's shape changed.

virtual inline void tick() override : The hot tick, which by default ticks every enabled child and times each.

inline std::size_t trailSamples() const : Test seam: how many trail samples both planes hold, since a rendered frame cannot show a stale plane.

inline uint16_t trailAt(std::size_t i) const : Test seam: read one trail sample across both planes, where past the end reads 0.

Public Static Attributes

constexpr uint8_t kMaxDots = 8 : the dots control's ceiling

constexpr uint32_t kMaxEmitters = 64 : the ceiling once dots is scaled by the grid

Public Static Methods

static inline lengthType spanRadius(lengthType span) : The head's radius: one light on a panel, larger as the grid grows, capped for a wall.

More info

The plane is 16-bit, and that is the point

A trail is a value multiplied by slightly less than one, hundreds of times a second. At 8 bits that truncates to nothing, or rounds back up and the effect turns solid. [draw::decay] carries the measurements. So the plane is wider than the layer it writes to and narrows once on the way out. The precision belongs in the accumulator rather than in the frame buffer.

Cost and the volume

One advect, a bilinear sample per light, plus one noise sample per light for the flow. The flow rule dominates. On a cube each slice gets its own flow, sampled at that slice's depth. Light travels within a slice: advect16 yields vx and vy, so a trail stays in its plane. Transport through the volume needs a trilinear sampler and a vz, which is its own change.