2.0p-340 Release Notes

https://github.com/VoxelPlugin/VoxelPlugin/tree/2.0p-340.0 - Released October 2 2023

This release drops 5.1 support and adds 5.3 support.

New features

New material pipeline

The new voxel material pipeline is now ready, letting you assign materials per voxel. You can have up to 3 different materials per "texel" (ie, per detail texture pixel). Rendering supports blending up to 3 materials as well.

You can have a few thousands of materials per chunk. The only limitation is that voxel materials need to all inherit from the same material definition: each voxel material can have its own parameters (float/textures), but the material logic needs to be shared between all of them.

For more details see Material Definitions and the Complex Material example.

New foliage pipeline

Foliage has been refactored into a point-based spawning system, following design patterns similar to Unreal's PCG. Existing foliage graphs will be broken, you will need to manually migrate to the new system. See Foliage and the LandmassFoliage example.


This pipeline supports invoker-based collision and has been stress tested in large projects: collision is only generated near invokers to reduce the load on the Chaos scene and avoid hitching. The new invoker system is designed to support up to 500 invokers to allow adding one to every gameplay object.


You can use MakePointHandle to get a point handle from a hit result. This handle is globally unique, replicable, serializable into save games and can be sent through RPCs.

With this handle, you can edit point attributes at runtime: you can change a point scale, location, or even set more complex attributes and react to them in your graph.

New sculpting pipeline

The sculpting pipeline is now close to being ready. It can already be used to sculpt terrain features, both in the editor and at runtime. Sculpt data is stored per voxel actor, allowing you to sculpt individual brushes. Sculpt tools themselves are voxel graphs, making it easy to make custom tools.

Currently, the distance field generated by sculpt data is incorrect and will get worse the more your sculpt. This will result in various glitches, including uneven sculpt speed and holes in the terrain. Additionally, sampling sculpt data has not yet been optimized, and as such is fairly slow. Performance will be improved in the next release.

Sculpting at runtime currently requires spawning a new voxel actor with the sculpt tool graph attached to it, and then calling ApplySculpt. This will be improved down the road so that spawning an actor is not required.

To try out some sculpt tools, install the Sculpting Tools example.

New surface pipeline

The voxel distance type has been removed and replaced by surfaces. A Surface is a high level object representing a shape: it might be a single brush, or the union of many brushes.

In addition to distance, surfaces also store material data and can store arbitrary attributes. Typically, you could store a float attribute Roughness in your surface & use that in your material.

Practically speaking, not much has changed: you can use MakeHeightSurface, MakeVolumetricSurface, MakeSphereSurface or MakeBoxSurface to make a new surface. You can then merge these surfaces using SmoothUnion/SmoothIntersection. Merging surfaces will automatically blend their materials and attributes.

See Working with Surfaces for more details.

Graph preview and debug

You can use R on any node to preview its output in the preview window on the right of the graph editor. Read the Graph Preview article for information on how to use it.

Pressing D will debug the selected node. Debugging a node can do one of two things; if the node is used in the marching cube mesh query, its output will be debugged as color on the mesh itself. If the node being debugged is a point set for foliage, its output will be displayed instead of the final points. If the node being debugged is not used in a Render Mesh or Generate Marching Cube Surface node, debugging it will do nothing.

Lumen support

Lumen and distance field generation is now supported. You can enable it by enabling Generate Distance Field on the Generate Marching Cube Surface node.

This feature will use quite a bit of GPU memory. We recommend only enabling it on nearby chunks, typically using LOD <= 2 as condition.

There might still be issues with Lumen in packaged games - we will iron this out in the future.

Other features

  • Graphs have a new Compile All button to easily compile all voxel graphs in your project

    • Graphs with errors will automatically open

  • Graphs now support array types

  • Graphs now support recursive parameters

    • This is used in VS_Template to setup recursive clustering

  • Graphs have a new execution flow

    • All exec nodes (red nodes) now have an optional execution pin

    • Exec nodes in the main graph that have nothing connected to their exec pin will be executed automatically

    • You can use the Execute node to call exec nodes that are located in macros (these are not called by default)

    • You can use the Select node on execution wires to selectively enable/disable parts of your graphs

  • Graph instances have parameter tickboxes

    • You can now selectively override parameters in instances, with a tickbox similar to material instances

    • Existing parameters will be automatically enabled.

  • Voxel Actors can now be moved and fully support actor transforms

    • Brush transforms are detected relative to the actor they affect

    • Typically, if you have a planet with brushes attached to it, moving the planet will not trigger any refresh as the brush transforms relative to the planet will not change

  • Voxel Graphs now support thumbnails

    • You need to tick EnableThumbnails in your graph settings

    • Note that thumbnails might cause additional crashes

    • Use with the CreatePreviewMesh node

  • Detail texture improvements

    • Detail textures are now pooled into larger textures. This reduces render thread cost when voxel chunks are updated.

    • You can easily sample detail textures in materials using the new SampleVoxelFloatDetailTexture node

    • You can easily assign detail textures in graphs using SetSurfaceAttribute and BindFloatAttributeDetailTexture

  • Curve improvements

    • Curve sampling has been moved to ISPC, making sampling curves up to 10x faster

    • For best performance, keep the number of keys in your curve small

  • Stats improvements

    • To enable graph stats, use the Enable Stats button in graphs

    • Basic node stats: basic nodes will have their total run cost and per voxel/point cost displayed

    • Exec node stats: exec nodes will have their total runtime displayed. Typically, this is useful to easily spot which foliage instance is taking time to generate.

Technical notes

  • LLM memory tracking and Insights memory tracking are now fully supported

    • We did a full pass on memory allocations and fixed several leaks in the plugin

  • New task bypass option to make it easier to debug voxel task: pass -VoxelBypassTaskQueue or use voxel.BypassTaskQueue

  • VOXEL_ON_COMPLETE doesn't take a Thread anymore. Use VOXEL_ON_COMPLETE_GAMETHREAD to run on the game thread

  • SceneNode are now ExecNodes

  • You can use -checkVoxelNaNs or voxel.CheckNaNs to raise ensures whenever a NaN is generated


  • On runtime shutdown, the game thread will stall until all voxel tasks are completed or cancelled. This shouldn't create major hitches and will help having cleaner logic in subsystems.

  • The move to Channel Registry assets means we need to wait for them to be loaded before creating any voxel runtime. See FVoxelRuntime::CanBeCreated

  • Dense/morton-order position queries are now gone as using them to computed derivatives proved inaccurate

  • FVoxelPointId are only unique within a single foliage chunk. FVoxelPointHandle is globally unique. Serialization might fail if the graph that spawned the points are not loaded. Serialization requires voxel actors to have stable names.

  • You can now use the ConstantPin tag in exec node pins. This will compute the pin value before the exec node runtime is created and will recreate the runtime on value change. Use GetConstantPin(Node.PinName) to get the pin value in the exec runtime.

    • This replaces DECLARE_VOXEL_PIN_VALUES which is now removed

  • Any allocation done inside a VOXEL_FUNCTION_COUNTER will have the voxel LLM tag

  • The rotator pin type has been removed and Quaternion pins now break into euler angles instead

  • You can now use the voxel.get and voxel.set console commands to easily set voxel parameters at runtime

  • All voxel singletons now inherit from FVoxelSingleton and are destroyed on shutdown

    • This helps with memory leak detection as we can now ensure that all allocations made through the voxel allocator are freed on shutdown

    • This might cause crashes if you try to access any voxel singleton after the voxel module is unloaded (typically through an async task)

  • FVoxelTicker is now manually registering instances and they are all ticked together in FVoxelTickerManager::Tick

  • This release includes multiple bug fixes for running Unreal on a Linux system with Vulkan

  • VOXEL_CONST_CAST is now ConstCast

  • voxel.StartInsights and voxel.StopInsights can be used to easily start/stop an insights capture with the right settings.

  • To quickly hide a point, use SetPointVisibility. This will bypass the attributes and hide the point/disable its collision with at most a one frame delay.

  • When attributes are changed, new foliage instances will be detected and rendered through an UInstancedStaticMeshComponent to not trigger a full rebuild of the UHierarchicalInstancedMeshComponent tree. Instances will be removed by setting their scale to 0. If too many instances are changed at once, a full rebuild is triggered.

  • Recursive graph parameters

    • You can now have foliage recursively call on itself

    • This is useful for clustering

    • Detail panels are generated on-demand

  • Detail textures pools grow on-demand and never shrink. This might result in high memory usage. Use stat voxelmemory to see detail texture memory usage.

Migration notes

  • Array support in graphs

    • You can now use arrays in voxel graphs

    • This is currently used by the Random Select node

  • You can now use the Compile All button in graphs to easily see graphs with errors

  • Exposed Data nodes are gone - please use Register to Channel/Query Channel instead

  • Voxel Scene, Voxel Brush and Voxel Foliage graphs are now all Voxel Graphs

    • They will be automatically migrated

    • Voxel Meta Actor and Voxel Brush Actor are now Voxel Actor

  • The Distance pin type has been removed and is replaced by Surfaces

    • Surfaces are a high-level way of defining 3D shapes

    • Make Height Distance is now Make Height Surface

    • To create a surface from a SDF, use Create Volumetric Surface

  • Voxel Channel are now project settings and can also be defined in Channel Registry assets. Existing channels and their references will be automatically migrated to the new system.

  • Density Canvases are gone and replaced by sculpt surfaces

  • Foliage nodes are broken and will need to be migrated to the new system

  • Voxelized Mesh Assets will have their VoxelSize reset to 20cm

    • This is due to the removal of the project settings BaseVoxelSize

  • Physics Scene are removed, you can now directly use the Generate Marching Cube Collision and Navmesh node

  • The Graph property of Voxel Components is now private. You'll need to use the Set Graph function

  • ConstructBrush/UpdateBrush/DestroyBrush are now CreateRuntime/DestroyRuntime. UpdateBrush doesn't need to be called anymore when moving a voxel brush.

  • Local Variables must always have a declaration now. Existing local variables without a declaration will have one added on load at the center of the graph.

  • The Voxel/MaterialFunctions content folder has been entirely removed. If you are missing material functions, copy them over from a previous voxel release.

  • Perlin noise has been slightly offset to avoid glitches when querying at integer locations. This might affect existing maps using perlin noise.

    • GetPerlin2D: offset is (0.04902460144, 0.02112610644)

    • GetPerlin3D: offset is (0.04902460144, 0.02112610644,0.06403176963)

Last updated