Instancing

The module provides an instancing system with the VoxelInstancer node. This node must be added as child of a voxel terrain. It allows to spawn 3D models on top of the terrain's surface, which can later be removed when modified.

It can spawn two different kinds of objects: - Multimesh instances. They can be extremely numerous, and can optionally have collision. - Scene instances. They use regular scenes, however it is much slower so should be tuned to low numbers.

This system is primarily intented at natural spawning: grass, rocks, trees and other kinds of semi-random foliage. It is not suited for complex man-made structures like houses or villages, although scene instances can be used in some cases, if the available features suit your game.

This feature is currently only available under VoxelLodTerrain.

VoxelInstanceLibrary

Library setup

In order to spawn items, VoxelInstancer needs a VoxelInstanceLibrary resource. This resource contains a list of all the items that can be spawned, and how they will be placed.

Select a VoxelInstancer. In the inspector, assign a library to the library property, or create a new embedded one. Then click on the library resource. Now a menu should show up in the top bar of the main viewport:

Screenshot of the VoxelInstanceLibrary menu

In this menu, you can add items to the library by clicking VoxelInstanceLibrary -> Add Multimesh item.

Items created this way come with a default setup, so you should be able to see something appear on top of the voxel surface.

Note

If you are making a planet, you may want to set the up_mode of VoxelInstancer to Sphere mode. This will tell the instancer where the upward direction is, and will align the items according to the local origin of the terrain.

Block LOD

The range at which items spawn is based on the LOD system of the voxel terrain itself. This is configured in the lod_index property of VoxelInstanceLibraryItem. For example, choosing 0 will make the item spawn at the closest range, and fade quickly in the distance. Higher indexes will spawn on a larger range, so will also start to appear earlier as the player gets closer. Instances spawn in the same "blocks" as the ground.

Screenshot showing the effect of lod_index on the range of instances

Usually landscapes may be composed of multiple layers so that the closer you get, the more details come in. Bigger items use high lod indexes to be seen from far away, while smaller items may use lower indexes.

Screenshot of landscape using layers of instances

There is a balance to consider when choosing the appropriate lod_index: currently, larger indexes are much more imprecise, because they work on top of a lower-resolution mesh. When getting closer, it's possible that such instances are seen floating above ground, or sinking into it. This mostly happens in areas with sharp changes such as ridges, crevices or caves:

Screemshot of misaligned instances

To combat this, you can adjust the offset_along_normal parameter in the generator associated to the item. This depends on the asset, so designing them such that they can have part of their bottom sunk into the ground can give some margin of error.

Sometimes it might not be enough, so this problem still has to be worked out in the future. Possible approaches include:

  • Querying the world generator to approximate the surface without using the mesh (not suitable if the ground was edited)
  • Gradually snap the instances somehow as higher-resolution data becomes available
  • Load edited voxels for the entire world at once so they can be queried even from far distance (takes more memory)

Note

When making grass or other items, it may be a good idea to fade meshes based on distance from the camera using a custom shader, so they won't disappear abruptly. Using a ground texture of similar colors also helps to make it blend.

Mesh LOD

A secondary LOD system is included, which applies to meshes themselves, to some limited extent. Godot 3 does not have a LOD system (Godot 4 will), so this allows to reduce vertex count over distance from within a set of visible meshes.

To use this, you have to fill the 3 mesh LOD properties on your VoxelInstanceLibraryItem:

Screenshot of mesh LOD properties

If only the mesh property is set, no LOD will be used.

The distance at which a LOD will be chosen is currently hardcoded, because it depends on the lod_index the blocks for that item are loaded into, which in turn depends on the split_scale property of the parent voxel terrain.

Screenshot of mesh LODs with colors

If you need fewer LODs, you can assign twice the same mesh. This system is quite rigid because in Godot 4 it might be changed to only have a single slot dedicated to impostor meshes. Indeed, Godot 4 might support LOD on meshes, but it is not planned for the last LODs to become impostors, so this should still be possible to achieve.

Note

Impostor meshes are simple quads that can fake the presence of the real model over far distances. For example, this is a really fast way to render forests from afar, while being able to use detailed trees when coming closer.

Edition

Editing instances manually in the editor is not supported yet. It is only possible to define where instances spawn by using procedural generation.

It is however possible to remove them from within the game, when digging the ground they spawned on.

Persistence

It is possible for some items to be persistent. This option can be enabled with the persistent property of VoxelInstanceLibraryItem. If the parent terrain has a VoxelStream supporting it, then instances from edited blocks will be saved into the stream, and won't respawn next time the player gets close to the area. Non-persistent instances will always respawn on each surface where procedural conditions are fulfilled.

The ID of persistent items is important, because it will be used in saved data. If you delete an item and try to load instances from a stream that still contains them, warnings will occur.

At time of writing, only VoxelStreamSQLite supports saving instances.

The save format is described in this document.

Setting up a Multimesh item from a scene

It is possible to setup a Multimesh Item from an existing scene, as an alternative to setting it up in the inspector. One reason you could need this is to setup colliders, because although they are supported, it is not possible to set them in the inspector at the moment. It might also be more convenient to design instances in the 3D editor using nodes.

This conversion process expects your scene to follow a specific structure:

- PhysicsBody (StaticBody, RigidBody...)
    - MeshInstance
    - CollisionShape1
    - CollisionShape2
    - ...

Materials can be setup in two ways: - material_override on the MeshInstance - Materials on the mesh resource directly

Surface material properties on the MeshInstance are not supported.

Scene instances

Multimesh items are fast and efficient, but are quite limited.

Instancing scenes is supported by adding items of type VoxelInstanceLibrarySceneItem. Instead of spawning multimeshes, regular scene instances will be created as child of VoxelInstancer. The advantage is the ability to put much more varied behavior on them, such as scripts, sounds, animations, or even further spawning logic or interaction. The only constraint is, the root of the scene must be Spatial or derive from it.

This freedom has a high price compared to multimesh instances. Adding many instances can become slow quickly, so the default density of these items is lower when you create them from the editor. It is strongly recommended to not use too complex scenes, because depending on the settings, it can lead to a freeze or crash of Godot if your computer cannot handle too many instances.

Warning

If you add a scene to the library and then try to load that library from that same scene, Godot will crash. This is a cyclic reference and is hard to detect in all cases at the moment.

Procedural generation

Built-in generator

Screenshot of a layer of instances using noise

Items are added with a default built-in generator, so they will already spawn based on procedural rules rather than being painted manually. You can tweak the generator by inspecting the generator property of VoxelInstanceLibraryItem.

Persistent instances located in a block that was edited in the game will no longer regenerate.

Custom instance generator

The feature is recent and the API may still change, so this is not available to scripts at the moment.

Streaming events (advanced)

VoxelInstancer knows when to spawn things by registering itself to its parent's block events. This is currently not available to the script API of VoxelLodTerrain, but may be added in the future.