Work with volumes

Volumes are a type of geometry that is available in Bifrost. Volumes are the natural output of aero and combustion simulations, and you can create and render compelling effects using only high-level compounds. However for some specialized purposes, you may need to understand a bit more about the inner workings and structure of volumes.

Like most other programs, Bifrost's volumes consist of voxels — small cubes that fill 3D space analogous to how pixels are small squares that fill a 2D image. The values of a volume's properties can vary from voxel to voxel. Common float properties include voxel_fog_density, voxel_temperature, and voxel_signed_distance, while common float3 properties include voxel_velocity and voxel_acceleration.

Volumes are similar to Bifrost fields in the sense that they represent values throughout space. However, fields are based on formulas that can be computed at any position while volumes store values that are sampled at the discrete voxel positions — values in-between exact voxel positions must be interpolated from the surrounding voxels.

Level sets versus signed distance fields

The properties of a volume typically represent values that vary smoothly and continuously across space, even if values are stored only for discrete voxels. For float properties, you can imagine drawing surfaces of constant value called level sets, similar to elevation contour lines on a topographical map or isobars on a weather map. In the case of temperature, such a level set might be an irregularly shaped envelope around a heat source where it has warmed the ambient air by a specific amount.

A diagnostic slice showing temperature values through an explosion. Similar circles represent similar temperatures.

Because a level set is a surface, you can create a mesh from a volume with a scalar property by using the volume_to_mesh node and specifying the level_set_threshold (sometimes called the iso value) that you want. The resulting surface can be complex, such as for specific temperatures around around multiple heat sources — in this case, a high threshold might yield disjoint surfaces close to each source anad a low threshold might yield a single contiguous shape surrounding all the surfaces.

The distance from any point in space to the closest location on a closed surface forms a special kind of level set called a signed distance function or signed distance field (SDF). In computer graphics, distances outside the surface are considered positive and distances inside the surface are negative.

When you convert geometry to a volume with store_level_set enabled, the resulting voxel_signed_distance property contains the values of the signed distance function sampled at the voxel positions. The 0 level set represents the original mesh surface — you could use this to reconstruct the mesh, more or less accurately depending on the resolution of the voxels. In addition to voxel_signed_distance, the volume may contain other properties sampled from the input mesh, such as colors.

It is important to remember that, while any level set can be used to construct a mesh surface, not every level set represents a signed distance function. Following a gradient from higher to lower values always means that you are getting closer to the surface (the 0 level set) in a signed distance field, but this is not true when the values represent something like temperature — you might just be approaching the center of a slightly cooler region with warmer values all around it. Some algorithms require a signed distance function, and don't give sensible results with an arbitrary level set.

Voxels and tile trees

Bifrost volumes use sparse voxels — instead of evenly dividing a potentially enormous bounding volume, voxels are created only where needed. For example, voxels may only around aero sources to contain the emitted fog or only near the surface of a converted mesh. Sparse voxels are also used in other volume formats, such as VDB. Like in VDB, nearby voxels are organized into blocks called tiles.

Bifrost's voxels can also have different sizes, unlike most other volume formats including VDB. This saves memory, because calm regions with low fog density do not need as much detail as turbulent regions with higher density.

The voxels are arranged in a multi-resolution tile tree, where larger, coarser voxels can serve as the tiles for the next finer level of voxels. Voxels that don't contain any child voxels are called leaf voxels. The data in a non-leaf voxel is the average of the values in its children.

When iterating over the voxels of a volume, it is sometimes necessary to use get_volume_tile_info to check whether each voxel is a leaf before doing something with it.

Using `get_volume_tile_info` to check whether a voxel is a leaf