MudBun is a volumetric VFX mesh tool for Unity. It procedurally generates meshes from “brushes” that define shapes (VFX & primitives), distortion, and shape modification.
Join the Discord server to discuss MudBun and other tools!
Inspired by Clayxels’ use of the marching cubes algorithm, MudBun started off as an offshoot of an open-source research project on ray marching and optimization with spatial data structures, now focused on procedural volumetric VFX mesh creation. Relevant resources and references for MudBun’s core tech are appended at the bottom of this page.
Great Combo with Boing Kit
MudBun can be used to create organic-looking mesh, which makes it a great combo with Boing Kit, a tool for producing organic bouncy effects.
- Unity 2019.3 or newer.
- Platforms with graphics APIs that support compute shaders, including Direct3D 11/12, Metal, Vulkan, OpenGL 4.3+, OpenGL ES 3.1+, and modern consoles (PS4 and Xbox One).
- Noise features depend on inline sampler states, which are only supported by Unity for Direct3D 11/12, Metal, and modern consoles (PS4 and Xbox One).
Here is a quick list of key features with more details below.
- SDF-based volumetric mesh generation.
- Real-Time Iteration
- VFX & Primitive brushes.
- Distortion & modifier brushes.
- Custom brushes.
- Render modes: smooth mesh, flat mesh, splats.
- Brush materials.
- Smooth splat scaling.
- Dynamic voxel density.
- Mesh collider generation.
- Mesh locking & auto-rigging.
- Render pipelines supported: built-in RP, URP, HDRP, and custom RP.
- Custom shader nodes.
- Borderless voxel space. (*)
- Optimization with spatial data structures.
- GPU memory budgeting & auto adjustment.
SDF-Based Volumetric Mesh Generation
A signed distance field (SDF) is a function that takes a point in space and returns how far away the point is from the surface of a shape. When the value is positive, the point is outside the shape; when the value is negative, the point is inside the shape. This is a way to implicitly define solid shapes that might be otherwise difficult or impossible to express using explicit equations.
There are various algorithms for generating meshes from SDFs. The marching cubes algorithm is a very common one, and is used in MudBun.
The effects are interactive in real time, both in editor and at run time. This allows rapid iteration.
VFX & Primitive Brushes
Each element that contributes to the final SDF is called a “brush”. There are 3 types of brushes: solid, distortion, and modifier.
One of the nice properties of using SDF is that it’s easy to combine solid brushes with Boolean operations, a process also commonly known as constructive solid geometry (CSG). MudBun supports the following operations: union, subtraction, intersection, and dye (contribute material without changing geometry).
Further, these operations can blend brushes together smoothly.
MudBun provides several solid brushes geared towards VFX, including noise volumes, particles, and noise along curves.
MudBun’s noise volumes support 2 coordinate systems: Cartesian and spherical. Noise in Cartesian coordinates is sampled using the typical (X, Y, Z) coordinates. Noise in spherical coordinates is sampled using the (r, θ, ϕ) coordinates, where the first component is the distance from the brush’s origin. This is useful for creating radially-scrolling noise.
Taking the intersection of a scrolling noise in spherical coordinates with other shapes can create some interesting effects.
In addition, MudBun provides several basic solid primitive brushes, including boxes, sphers, cylinders, cones, tori, solid angles, simple curves (2 end points + 1 control point), and full curves (any number of interpolated points). They can be used to create various shapes.
Distortion & Modifier Brushes
MudBun also offers distortion and modifier brushes to further affect the mesh’s shape. Distortion brushes manipulate the positions of sample points, whereas modifier brushes post-process and change the values of the accumulated SDF.
MudBun provides straightforward means to create custom brushes. Users can create solid brushes with custom SDFs, as well as custom distortion & modifier brushes. Details on how to do this are described in the user manual.
There are three render modes: smooth mesh, flat mesh, and splats.
The smooth mesh mode is for generating meshes with smooth normals. In order to generate the smooth normals, this mode needs to sample the same SDFs multiple times, so its performance is worse than the other two modes.
The flat mesh mode is for generating meshes with flat normals. It doesn’t need to sample the SDFs multiple times, so its performance is better than the smooth mesh mode. Depending on the user’s desired visual style, flat normals might be more desirable than smooth normals. Rendering flat meshes at low voxel density can create a stylized low-poly look to the mesh.
The splats mode is for generating splats at voxel cells. Think of it as a bunch of sprites scattered across the surface of the solids. The performance is similar to the flat mesh mode. Changing the sizes, facing, and textures of the splats can create various kinds of stylized looks.
A brush is associated with a material. These materials blend together as the brushes are blended together.
Each brush has a material component, where the user can define the brush’s material in-place, or assign a shared material stored as an asset. Material properties that are blended include color, emission, metallic, and smoothness, which are typical physically-based rendering (PBR) properties.
[WIP Feature] Additionally, there is a special integer property valued between 0-3 that is “blended” differently. Each integer value corresponds to a weight, which is the value that is actually blended. The weight corresponding to the material’s special integer property value is set to 1, and the others set to 0. These blended weights can be used to blend among discrete properties, such as textures.
Smooth Splat Scaling
When using the splats render mode, splats are smoothly scaled up or down as they approach or leave, respectively, the solid boundaries of SDFs. This produces smooth transition and avoids pops (temporal discontinuity), especially when the SDFs are changing slowly and smoothly, such as slow-scrolling noise.
Dynamic Voxel Density
The voxel density can be dynamically changed at run time. Lower voxel density means less voxels and better performance. This is useful for targeting different platforms with different performances. It can also be used to create stylized transitions.
Mesh Collider Generation
Mesh colliders can be generated, either added to the renderer itself or a new separate game object. The voxel density for generating the mesh collider doesn’t need to be the same as that of the renderer.
Mesh Locking & Auto-Rigging
The procedurally generated mesh can be locked in to become a standard mesh. There is also an option to auto-rig the locked mesh with brushes. This is handy for getting everything done quickly without leaving the Unity editor, and the auto-rigged mesh is ready for use with procedural animation tools like Boing Kit.
Render Pipelines & Shader Nodes
MudBun supports Unity’s 3 standard render pipelines: built-in RP, URP, and HDRP. However, custom scripted render pipelines can also be supported.
Amplify Shader Editor is used to create MudBun’s default shaders for the URP and HDRP. The common shader functions are isolated in custom Amplify Shader Editor nodes. There is one node for the mesh render modes and one for the splats render mode.
These shader nodes can be used to create custom shaders for the 3 standard render pipelines, as well as for custom scriptable render pipelines.
MudBun’s default shaders for built-in RP remain handwritten to serve as ground truth.
[WIP Feature] Support for Unity’s built-in shader graph will begin once some missing features (probably by accident) are implemented by Unity.
Borderless Voxel Space
Volumetric solutions are commonly constrained within the borders of a dense finite voxel grid. However, MudBun breaks this constraint (*) by employing spatial hashing and sparse voxel trees. The user doesn’t have to worry about the constraints of a finite voxel grid when working within typical game settings.
(*) Technically, there is still a limit, but it’s much larger than a typical dense finite voxel grid. MudBun’s limit is a grid of 262k^3 voxels. If somehow the user needs to go outside this limit, it can be easily accommodated by shifting the renderer around, since the grid is relative to the renderer’s center.
Optimization with Spatial Data Structures
MudBun uses bounding volume hierarchies (BVHs) to optimize performance. This can effectly cut down the number of brushes processed for each voxel. A brush is only processed for a voxel if its bounding volume intersects the voxel, where the bounding volume is expanded by the blend distance, distortion distance, and/or modifier distance, in order to avoid false rejection.
[WIP Feature] Right now, each particle system uses a single bounding volume that encompasses all underlying particles, which means there can be many particles unnecessarily processed for voxels that are obviously too far away. There are plans to treat particles differently with additional dedicated data structures to improve performance.
GPU Memory Budgeting & Auto Adjustment
MudBun offers straightforward interface for budgeting GPU memory, as well as diagnosing its usage. There is also an option to keep track of high-water marks and automatically adjust the GPU memory usage accordingly, with an adjustable margin percentage just to be safe.
Tech Resources & References
- Tech references used for Clayxels documented by Andrea Interguglielmi.
- Research project on ray marching and spatial data structures.
- The marching cubes algorithm for generating mesh from SDFs.
- SDF primitives and normal generation math by Inigo Quilez.
- Dynamic bounding volume hierarchy in Box2D by Erin Catto.
- Spatial hashing based on GPU hash table by David Farrell.
- Noise formulae based on webgl-noise.