Raymarcher Technical & APi Documentation
RM Volume Voxel Painter
Namespace: Raymarcher.Toolkit
The Volume Voxel Painter is a regular class that enables you to modify a RT3D (Render Texture 3D).
It requires proper initialization with the target tex3DVolumeBox or the RT3D, target common volume resolution, and the option to use an initial volume canvas.
Remember to call 'Dispose' to release sensitive resources created.



The Voxel Painter allows you to paint pixel data to a target RT3D.
These data are represented in the red channel of an RT3D.
Additionally, there is a green channel used for materials mapping, and an extra blue channel for custom purposes.

These pixel data can be later utilized in a specific tex3DVolumeBox, generating voxels with materials based on the painted information.
Properties & Fields
public bool IsInitialized { get; }
// Is this voxel painter class initialized for a specific tex3DVolumeBox gameObject or just purely for 3D render texture?
public bool IsInitializedWithTargetTex3DVolumeBox { get; }
public int TargetVolumeResolution { get; }
public CommonVolumeResolution TargetCommonVolumeResolution { get; }

public RMSdf_Tex3DVolumeBox TargetTex3DVolumeBox { get; }
public RenderTexture TargetWorkingRT3D { get; }
public Texture3D InitialTex3D { get; }
Methods
// Initialization Constructors

// Initialize the voxel painter with the common volume resolution, existing tex3DVolumeBox component and (optional) initial volume 3D Texture (it will override the current volume texture of the targetTex3DVolumeBox)
public RMVolumeVoxelPainter(CommonVolumeResolution targetCommonVolumeResolution, RMSdf_Tex3DVolumeBox targetTex3DVolumeBox, Texture3D initialVolumeTexture3D = null)
// Initialize the voxel painter with the target 3D render texture (must be in the Raymarcher's common volume resolution)
public RMVolumeVoxelPainter(RenderTexture targetRT3D)

// Manual Initialization Methods

// Initialize the voxel painter for an existing tex3DVolumeBox component with the common volume resolution and (optional) initial volume 3D Texture (it will override the current volume texture of the targetTex3DVolumeBox)
public void InitializeForTargetTex3DVolumeBox(CommonVolumeResolution targetCommonVolumeResolution, RMSdf_Tex3DVolumeBox targetTex3DVolumeBox, Texture3D initialVolumeTexture3D = null)
// Initialize the voxel painter for an existing 3D render texture
public void InitializeForTargetRenderTexture3D(RenderTexture targetRT3D)

// Update Methods

// Do not dispose sensitive resources, but update the current voxel painter instance with a new render texture and assign it to the target volume box (if possible)
// Call this function if you won't to dispose current 3D render texture and update the voxel painter with a new 3D render texture only
public bool UpdateNewTargetRT3D(RenderTexture newTargetRT3D, bool updateTargetTex3DVolumeBoxIfExists = true)
// Assign a new target tex3DVolumeBox gameObject only (does not dispose anything, only updates the volume box for this voxel painter)
// You can use both functions to switch between different tex3DVolumeBoxes without loosing data in the existing 3D render textures
public void AttachNewTargetTex3DVolumeBox(RMSdf_Tex3DVolumeBox newTargetTex3DVolumeBox)

// Disposal Methods

// Set the current 3D render texture and target tex3DVolumeBox object to null only (This will not dispose anything)
public void DetachResources()
// Dispose the current voxel painter instance
public void Dispose()

// Modification Methods

// Paint voxels in the current 3D render texture in world-space coordinates
// Use 'modulo-wrap' to repeat the volume-space coordinates inside the volume box. Meaning that if the player is outside of volume box, the coordinates will repeat within the volume box (this is useful if your volume box is using any 'mirrored-repeat' modifiers)
public void PaintFullVoxel(Vector3 worldSpaceCoordinates, float worldSpaceRadius, float brushIntensity01 = 0.5f, float brushSmoothness01 = 1, bool erase = false, MaterialData materialData = default, bool moduloWrap = false)
// Paint voxels in the current 3D render texture in volume-space coordinates (0-volume resolution)
public void PaintFullVoxelNative(Vector3 volumeSpaceCoordinates, float volumeSpaceRadius, float brushIntensity01 = 0.5f, float brushSmoothness01 = 1, bool erase = false, MaterialData materialData = default)

// Paint a material to voxels in the current 3D render texture in world-space coordinates
// Use 'modulo-wrap' to repeat the volume-space coordinates inside the volume box. Meaning that if the player is outside of volume box, the coordinates will repeat within the volume box (this is useful if your volume box is using any 'mirrored-repeat' modifiers)
public void PaintMaterialOnly(Vector3 worldSpaceCoordinates, MaterialData materialData, float worldSpaceRadius, float brushSmoothness01 = 1, bool moduloWrap = false)
// Paint a material to voxels in the current 3D render texture in volume-space coordinates (0-volume resolution)
public void PaintMaterialOnlyNative(Vector3 volumeSpaceCoordinates, MaterialData materialData, float volumeSpaceRadius, float brushSmoothness01 = 1)

// Paint a value to an extra voxel channel in the current 3D render texture in world-space coordinates
// Use 'modulo-wrap' to repeat the volume-space coordinates inside the volume box. Meaning that if the player is outside of volume box, the coordinates will repeat within the volume box (this is useful if your volume box is using any 'mirrored-repeat' modifiers)
public void PaintToExtraChannelOnly(Vector3 worldSpaceCoordinates, float worldSpaceRadius, float channelValue01, float brushSmoothness01, MaterialData materialData = default, bool moduloWrap = false)
// Paint a value to an extra voxel channel in the current 3D render texture in volume-space coordinates (0-volume resolution)
public void PaintToExtraChannelOnlyNative(Vector3 volumeSpaceCoordinates, float volumeSpaceRadius, float channelValue01, float brushSmoothness01, MaterialData materialData = default)

Practical Use
You can use the Volume Voxel Painter in your own C# script and dispatch all the parameters yourself, or you can leverage the example content provided by Raymarcher.
In the example content, there's a script named 'RMSample_VolumeVoxelPainterFPS' that contains all the necessary functionality, including handling input for an FPS character (legacy).

To integrate this functionality into your scene:

1. Assign the script to your character.
2. Set the required fields:
- Assign your target tex3DVolumeBox that you want to modify with voxels.
- Specify the desired volume resolution (higher resolution may impact performance).
- Optionally, assign the initial volume canvas; these canvases will be instantly painted to the volume box on start (canvas dimensions must match the selected common volume resolution).
- If your character contains a Volume Character Controller, disable the auto-init field on the controller and assign it to the Voxel Painter FPS field under the Addons header.
- If your character contains a Volume Brush Locator (this script allows you to sample a brush gameObject in the volume box), assign it to the Voxel Painter FPS as well.
- Assign the target brush transform under the Brush Settings header.

After setting up these fields, you should be ready to paint!

Voxel Material Painting
A Volume 3D texture is constructed with three channels: red (voxel building block), green (material override), and blue (extra data).
The second channel is typically used for material override, a functionality Raymarcher handles for you.

To add a VolumeMaterialCompositor modifier to your target volume box, follow these steps:

1. Add a VolumeMaterialCompositor modifier to your target volume box.
2. This modifier allows you to alter up to 4 different material types to the renderer.
Assign your materials to these fields, hit refresh, and you can override these materials on the voxels displayed in the volume box.

Note: All materials used in the slots must be the same type and belong to the same material family.
If one of the materials in the fields is of type 'SlopeLit', all the other materials must be the same type as well.

Painted materials are not applied separately; they are painted as 'biomes' layered on one another.
If you paint a material on index 2, all the other materials below that material index will be displayed on the 'edge' of the voxels.



Once the material compositor modifier is set, select the object with 'RMSample_VolumeVoxelPainterFPS' and assign the compositor to the required field:



Now, you can choose which material index will be painted on voxel painting.
You can observe the material index by going to the RaymarcherRenderer component, scrolling down to the materials, and preview the existing material instances in the session:



You can also limit the voxel painting based on the currently sampled material instance index from the green channel in the RT3D.
There is a field Max Material Instance Index which limits the voxel painting.
If the currently sampled voxel's material instance index (in the green channel) is less than the specified value, the painting is limited.
If this value is set to 0, the limitation is not used. This can be utilized to make some voxels with certain materials 'unremovable'.