Particle advection (foam, bubbles, etc)

Quoting wikipedia: "advection is the transport of a substance by bulk motion". Imagine a leaf floating on the surface of a river: wherever the river flow goes, the leaf follows. In this case, the leaf is being advected (carried) by the river.

40k fluid particles and 500k advected foam particles being simulated in the GPU (Compute backend).

Fluids in Obi can advect smaller, passive particles to simulate foam, bubbles, smoke, or add interesting internal details to a simulation. Since these advected particles do not perform any expensive simulation themselves (they are just passively carried by the fluid, and do not interact with other advected particles in any way), you can have many more advected particles than fluid particles. The maximum amount of advected particles that can be simulated by a solver can be set in the Memory budget section of the ObiSolver component.

Obi includes the ObiFoamGenerator component that will automatically generate advected foam particles in regions of turbulent (high velocity, high vorticity) fluid, and the ObiFoamEmitter component that allows you to generate foam particles in a specific area. You can also programmatically spawn/kill advected particles as well as modify their properties, check the scripting advection page.

How it works

Every physics update, Obi determines all fluid particles close to each advected particle. Then it sets the advected particle's velocity to the weighted average of all of its neighbor fluid particles. Fluid particles that are closer get higher weights, so they influence the final advection velocity more than particles further away.

The white spheres are fluid particles. The red dots are regular particles being passively carried the fluid.

Advected particles that get fewer than the ObiSolver's foam min neighbors parameter are considered to be spray particles and will continue to move under the influence of gravity, following a ballistic trajectory instead of being advected. You can scale the amount of gravity influencing spray particles and adjust a few other global advection parameters in the ObiSolver component.

Spray particles add some visual interest to violent splashes and crashing fluid. If you want to get rid of spray particles, you can either use a very high air aging parameter (see below) which will cause spray particles to age and die much faster, or you can write a simple custom component to identify particles with few neighbors and kill them. You can find sample code to do this in the scripting advection page.

Foamy fluid without spray particles.
Foamy fluid with spray particles, which add important visual detail.

Setup

To make a fluid ObiEmitter generate foam, simply add a ObiFoamGenerator component to it.


ObiFoamGenerator calculates and stores the amount of air trapped by each fluid particle during simulation, based on their velocity and vorticity (how turbulent the fluid is). This is called the foam potential. In addition to being used to determine where foam particles should be spawned from, it can be used to drive rendering effects on fluid surfaces. By default, transparent fluids with a diffuse map assigned will only render it in areas of high foam potential. See fluid rendering for details.

Foam potential, visualized as grayscale gradient: black = no foam potential, white = max foam potential.
Diffuse foamy texture added to a transparent fluid, only appears in areas of high foam potential.

Foam generation rate

Maximum amount of foam particles that can be spawned by a single fluid particle per second, as long as its foam potential is larger than zero. Note that once the solver's "max foam particles" is reached, no new particles will be emitted until some of the existing particles die.

Foam Potential

Maximum rate at which the potential for foam generation increases when fluid particles are within the velocity and vorticity ranges.

Foam Potential Diffusion

Determines how fast the foam potential fades out over time, in % per second.

Velocity Range

Particles within this velocity range (expressed in meters/second) will increase their foam potential. The closer their velocity is to the upper value of the range, the more foam particles will be spawned.

Vorticity Range

Particles within this vorticity range (expressed in radians/second) will increase increase the foam potential. The closer their vorticity is to the upper value of the range, the more foam particles will be spawned.

Color

Color of the foam particles. Using the included foam shaders, final transparecy (alpha) will be modulated with particles age so that they smoothly fade in/out. To control fade length, use the "Foam fade" parameter in the ObiSolver component.

Size

Maximum size of the foam particles.

Size random

Randomness applied to particle size. At 0, all particles will be of the same size. At 1, particle size will be randomly chosen between 0 and the "Size" parameter (see above). Use small values for a realistic look.

Lifetime

Maximum lifetime of the foam particles, expressed in seconds.

Lifetime random

Randomness applied to particle lifetime. At 0, all particles will have the same lifetime. At 1, particle lifetime will be randomly chosen between 0 and the "Lifetime" parameter (see above). Use small values for a realistic look.

Buoyancy

Force that opposes gravity, making foam float. Only applied to foam particles that are surrounded by fluid.

Drag

Amount of influence fluid velocity has on foam particles. At 1, foam particles will be fully affected by the fluid's velocity field and will ignore any external forces (including buoyancy, see above). At 0, particles will move freely. For liquids, use intermediate values (eg. 0.4-0.8) for realistic results.

Atmospheric Drag

Amount of influence air has on foam particles. At 1, foam particles that aren't near fluid (spray particles) will quickly lose all their kinetic enery when in contact with air. At 0, spray particles will retain all their kinetic energy. Use intermediate values (eg. 0.2-0.6) for realistic results.

Air Aging

Aging multiplier for spray particles. Increase this value to accelerate the speed at which spray particles age and die.

Isosurface

Density threshold used to tell apart the fluid's volume from the air surrounding it. A value of 0 sets the fluid's surface at the region where fluid density = 0. Higher values will retract the surface towards the fluid's volume.

Density control (Compute only)

These are advanced foam controls, available only when using the Compute backend. Density control performs a secondary pressure/density simulation for foam particles, which allows them to push away/pull in nearby foam particles to keep a specific foam density. This helps get rid of excessive clumping and streak/string like shapes that take place when relying purely on the fluid's velocity field.

The per-particle neighborhood built during density control is also used to calculate directional occlusion and light scattering, see rendering below.

Pressure

Scales the repuslive force applied by each foam particle on its neighbors. Set it to 0 to disable density control entirely, set it to 1 to use full pressure force.

Density

Sets the target foam density. Larger values will cause particles to pull neighbors in and clump together. Lower values will ensure foam particles do not clump together.

Smoothing radius

Size of each particle's neighborhood, expressed as a % of its size. Larger smoothing radius will allow foam particles to interact with more neighbors and yield higher quality results, but will increase the cost of density control.

Surface tension

Amount of surface tension applied to foam particles. Larger values will cause foam to clump into rounder shapes.

Collisions

By default, foam particles rely on neighboring fluid particles to handle collisions. This is extremely cheap as it doesn't require foam particles to perform any explicit collision detection, but it's not very effective - specially for spray/ballistic particles, as they have few or no fluid neighbors.

The compute backend can optionally perform full collision detection of foam particles against ObiColliders, you can enable foam collisions in the ObiSolver component. Collision response is inelastic and frictionless. This helps obtain sharp contact silhouettes and can make spray feel more "grounded" as it doesn't pass trough objects in the environment.

Foam collisions disabled, foam just follows nearby fluid particles which results in "fuzzy" collisions against the capsule collider.
Foam collisions enabled, each individual foam particle is tested for collisions which results in a sharp, clear silhouette where foam meets the capsule collider.

Rendering

Foam particles are rendered as uniformly colored ellipsoidal splats, each splat has a color and size determined by the ObiFoamGenerator/Emitter that spawned the particle. The size of all foam particles in the solver can be globally scaled using the ObiSolver's foam radius scale parameter.

Foam radius scale = 1. Individual particles can be clearly seen.
One way to fix this is to just make particles larger, by setting the solver's foam radius scale to 2.

Particle ellipsoids can orient themselves in the direction they're moving and and stretch depending on their velocity. This is an inexpensive way to simulate motion blur. You can globally control the maximum amount of velocity stretching using the ObiSolver's max foam velocity stretch parameter.

Zero maximum velocity stretch. Particles are perfectly round.
Non-zero maximum velocity stretch. Particles become ellipsoids, stretched along the direction they're moving.

Each individual particle has no shading of its own, however when using density control (only available in the Compute backend, see above) particles will calculate a directional occlusion value by looking at the position of other foam particles around them, measuring of how much light reaches each particle from the direction of the light.

This is a cheap way to simulate volumetric scattering, used to alter the color of particles using a single-scattering lighting model controlled by the ObiSolver's foam volume density, foam ambient density, foam scatter color and foam ambient color parameters. It's useful for large clumps of foam particles -such as thick foam or gases-, not so much for thin/sparse foam particles.

Gas rendered with low volume density. Shadowing is subtle, as light is let trough particles.
Gas rendered with high volume density. Shadowing is more defined, as foam particles absorb more light.