SDF Baker - GhislainGir/BlenderGameToolsDoc GitHub Wiki
Signed distance fields have seen widespread adoption in the video game industry over the past few years, thanks to their many versatile use cases. This tool streamlines the process of baking a signed distance field from one or multiple selected mesh objects, offering precise control over the field's volume.
Warning
This tool currently doesn't handle intersecting meshes well, so voxelizing the mesh to create a single unified one might be necessary if you encounter issues. Blender offers several voxelization options, such as the Remesh modifier.
A signed distance field is, as the name suggests, a field where each point stores the distance to the nearest surface. Positive values typically represent distances outside the surface, while negative values indicate distances inside it.
This field can be discretized in 2D using a texture, where each pixel represents the distance to the nearest surface at that point in 2D space.
The distance field can also be discretized in 3D using a pseudo-volume texture, where each voxel represents the distance to the closest surface at that point in the 3D volume.
Note
A pseudo-volume texture can be thought of as a regular 2D texture made up of multiple 2D slices arranged in a tiled sequence. Each tile represents a slice along the third dimension, effectively storing 3D volume data within a 2D texture.
While this type of texture can be sampled directly in most game engines, it requires additional math to convert a 3D UVW coordinate into the corresponding 2D UV coordinates within the tiled layout. Fortunately, most game engines—including Unreal Engine—support converting a pseudo-volume texture into a true 3D texture. This greatly simplifies sampling, allowing you to use UVW coordinates directly and let the GPU handle the rest.
By sampling the distance to the nearest surface at any point in the field, it's possible to compute a direction using derivatives. For example, sampling the field at a given point, and then slightly to the left of that point, reveals whether the distance increases or decreases in that direction. This indicates which way to go to get closer to the surface along the X axis. Repeat this process for Y and Z, and the resulting three components can be normalized into a direction vector. Combined with the sampled distance, this lets you estimate the exact position of the nearest surface:
Note
Several game engines—including Unreal Engine—make extensive use of distance fields and include built-in functionality to generate them from static meshes and other assets. However, these signed distance fields are often hidden resources, used internally by the engine and not easily accessible to the user. Additionally, the options for customizing how these distance fields are generated are often limited. That’s why having the ability to generate them in Blender can be incredibly useful.
The process of baking an SDF is quite straightforward, but before diving into it, let’s quickly go over the common options and panels.
The SDF tool allows you to define the volume to bake using two different modes, available in the 'Voxels' panel.
- Selection: The volume automatically encapsulates all selected meshes, with an optional extra offset in X, Y, and Z.
- Custom: The volume is based on the bounding box of a specified mesh or empty. If an empty is used, the volume is derived from its display size and scale and centered on its position.
Important
In both modes, the SDF tool generates a world-aligned bounding box.
This panel also allows you to adjust the number of voxels to bake along the X, Y, and Z axes.
Important
The number of voxels to bake along the Z axis determines the number of tiles in the texture. It's recommended to use a perfect square (4, 9, 16, 25, 36, 49, 64, 81, 100, etc.) so that the resulting texture can be a power-of-two with an equal number of tiles in both width and height. This isn't technically required but is the easiest option.
The X and Y values define the resolution of each tile. The higher the resolution per tile, the larger the overall pseudo-volume texture. A hardcoded 8K resolution limit is enforced.
A panel called 'Texture' lets you customize several options related to generating and exporting the SDF texture.
-
Distance: Control how distances are encoded in the texture
- Actual: Encode distances as-is, using the original units they were computed in
- Normalized: Normalize distances to the range [-1, 1]. The reported "Maximum Distance" can be used to remap the normalized values back to their original range
- Normalized & Remapped: Normalize and remap distances to the range [0, 1]. The reported "Maximum Distance", along with a constant bias scale, can be used to remap the normalized values back to their original range
- Filename: Name for the SDF texture file (without the .exr extension). is a placeholder tag that can be used to be replaced with the object's name
- Slices: Control how the tiles/z-slices are distributed in the texture. 'Bottom Top' is typically required for Unreal Engine or DirectX apps
- Slices Per Row: Specify how many Z slices to distribute along the U axis in the texture. For example, if you're baking 64 voxels in Z and set this value to 8, the result will be an evenly distributed 8×8 texture. If set to 10, it will produce a 10×7 layout, with 4 empty tiles in the last row
- Invert V: Invert the V axis of the UVMap for each tile/z-slice. Typically True for exporting to Unreal Engine or DirectX apps, False for Unity or OpenGL apps. This only affect each tile individually and doesn't affect the way they are sorted
- Two Sided: Assume mesh(es) are double sided, ignoring sign and computing the absolute distance. Useful for flat geometry, non-closed geometry etc
- Invert Sign: Flip the sign of the distance field (inside <> outside). Negative if inside and False, positive otherwise
-
Export: Enable to export the generated texture to an EXR file upon bake completion. Only available if the Blender file is saved
- Export|Path: Texture file path, excluding the file name. The path is relative to the Blender file
- Export|Advanced|Override: Enable to override any existing .exr file
A panel called 'Mesh' lets you customize several options related to generating & exporting the baked mesh.
- Scale: Scale applied during baking (e.g. meters to centimeters)
- Invert X/Y/Z: Invert the world X/Y/Z axis (Y set to True for Unreal Engine compatibility)
- Name: Name of the baked object
- Merged: Generate the mesh used for SDF computation (internally generated but destroyed afterward if False)
- Debug: Generate a mesh with a vertex for each sample point (useful for debugging)
-
Export: Enable to export the SDF bounds to an FBX file upon bake completion. Only available if the Blender file is saved
- Export|Name: Name for the exported FBX file (without the .fbx extension). is a placeholder tag that can be used to be replaced with the object's name
- Export|Path: File path for the exported FBX, excluding the file name. The path is relative to the Blender file
- Export|Advanced|Override: Enable to override any existing .fbx file
A panel called 'XML' lets you customize the export options for the XML file.
-
Export: Enable to export an XML file containing information about the bake process (recommended)
-
Export|Mode: Select how the XML file name and path are generated
- Mesh Path: Use the same FBX file name and path for the XML file. Defaults to 'Custom' if mesh is not exported
- Custom Path: Specify a custom XML file name and path
-
Export|Mode: Select how the XML file name and path are generated
- Export|Filename: Name for the exported XML file (without the .xml extension)
- Export|Path: Path for the exported XML file, excluding the file name. The path is relative to the Blender file
- Export|Override: Enable to override any existing .xml file
In most cases, it’s as simple as keeping the default settings, selecting the meshes you want to include in the bake, and clicking Bake.
To bake a 2D SDF, you'll want to set custom bounds, specify a flat mesh, set the amount of 'voxels in Z' to 1, and the 'frames per row' to 1 as well.
The result should be pretty straightforward to work with.
By default, the selected meshes are duplicated and merged into a single object (suffixed with '.source'). It may also be flipped based on the specified settings (mirrored in Y by default).
Important
If a flip is performed, normals are recomputed, which may result in unexpected face orientation in very rare cases.
Note
It's recommended to generate this mesh, even though it has limited use. Otherwise, you might wonder why the bounds aren't centered on the selection when an axis is mirrored. It also allows you to double-check the recomputed face orientation and ensure that all intended objects were correctly included in the bake. Its purpose is therefore mostly informative.
A world-aligned bounding box mesh representing the SDF volume is also created—this is the mesh that can be automatically exported as an .FBX file.
Additionally, a pseudo-volume texture is generated, storing the SDF tiles or Z-slices —this is the texture that can be automatically exported as an .EXR file. It typically needs to be saved in at least 16-bit float format, unless the SDF has been remapped to the [0:1] range. In that case, an 8-bit integer format is acceptable, as long as you're okay with the resulting loss in precision.
The texture can be imported directly into Unreal Engine and converted into a proper volume texture by right-clicking the texture asset and selecting 'Create Volume Texture'. You’ll likely need to adjust the 'Tile Size X' and 'Tile Size Y' settings to match the X and Y voxel counts you set in Blender.
Note
You may adjust the volume texture’s compression settings to best suit your use case.
The result can be easily visualized in Unreal Engine using Volumetric Fog and a Volume Material applied to the exported SDF bounds mesh, as demonstrated here.
Once a bake is attempted, a report panel will appear in the SDF Baker panel, providing valuable insights into the baked information.
- Export: Exports the report to an XML file following the XML export settings.
- Clear: Clears the report. This may be useful as the report holds pointers to the baked object(s), which will make them persist in the Blender file even though they are later deleted.
This panel provides global information about the bake that won’t be covered in detail in this documentation to avoid unnecessary clutter, as most of the information should be self-explanatory. However, there are a few things worth mentioning.
The 'Mesh' subpanel contains details about the baked volume's minimum and maximum extents, which can be useful if you need to reconstruct the SDF bounds mesh in case it gets lost.
The 'Texture' subpanel provides valuable information about whether the SDF was normalized and/or remapped, along with the maximum distance value, which can be used to remap the normalized SDF back to its original range if needed.
Warning
Self-intersecting meshes can lead to incorrect sign calculations when generating the signed distance field. This may result in visual artifacts in the texture—often referred to as "butterflies"—where isolated pixels have incorrect values. I'm hoping to eventually find a better solution, but in the meantime, if you run into this issue, try remeshing the geometry using voxelization (e.g. with the Remesh modifier).
Similarly, non-closed, non-manifold or any geometry weirdly broken in any way may lead to unexpected results.
Important
Mesh is the only supported object type, and this is unlikely to change. Curves can be converted to meshes, but they either generate only vertices and edges if they have no thickness—preventing a BVH tree from being generated—or produce non-closed meshes if caps aren't enabled. Ensuring a reliable curve-to-mesh conversion may be limiting, so users are instead encouraged to perform the conversion themselves if needed.
Finally, a 'Legacy' panel allows you to generate an SDF using geometry nodes. This process isn't streamlined and requires rendering the generated mesh with a top-down orthographic camera. It was deprecated in favor of a fully Python-based algorithm but has been retained for educational purposes, in case you find the geometry nodes graph useful.
The SDF Baker tool's configuration and settings can be saved as a preset, which can be easily applied with a single click at any time. Presets can be added or removed using the button located to the right of the SDF tool header.
This feature uses Blender's internal preset system, which creates Python files to store all the necessary data. These files are stored in the following directories:
- Windows: C:\Users\<your username>\AppData\Roaming\Blender Foundation\Blender\<version number>\scripts\presets\operator\databaker_sdf\
- MAC: Library\Application Support\Blender\<version number>\scripts\presets\operator\databaker_sdf\
- Linux: ~/.config/blender/<version number>/scripts/presets/operator/databaker_sdf/
Warning
Preset .py files can be copied, pasted, and shared across different computers. However, only install presets from trusted sources, as these files can execute malicious Python code on your machine.