Colored Microvoxels & Material Profiles

intermediate feature

Voxel Play 4 · Features

Voxel Play 4 extends the microvoxel system with custom color palettes and material profiles, enabling detailed decorations with per-cell coloring and dual-material surfaces like grass-over-dirt terrain.

Color Palettes

Each microvoxel shape can have a palette of up to 255 colors. Individual cells reference a palette slot, allowing detailed coloring within a single voxel.

  • palette: a Color32[] array storing the available colors
  • colorIndices: a byte[] with 4096 entries (16x16x16), one per cell. Value 0 = use parent material color. Values 1..N = use palette[N-1]

Requires VP_USE_TINTING enabled in the VoxelPlayEnvironment settings to render palette colors at runtime.

Layout Modes

The MicroVoxelLayout enum controls how primary and secondary materials are distributed across the microvoxel cells:

LayoutBehaviorUse case
DefaultAll cells use the primary materialStandard decorations, furniture, details
SlabsHorizontal split at secondaryTypeHeight. Cells below use primary, cells above use secondary material.Grass-over-dirt, snow-over-rock terrain surfaces
TopCapSide faces of the bottom half use the top-half texture from the secondary materialTerrain surface caps where sides need to show the top texture

The secondaryTypeHeight field (0-16) controls where the split occurs in Slabs mode. Default is 8 (midpoint).

Material Profiles

A VoxelMaterialProfile is a ScriptableObject that stores texture and PBR properties for a voxel surface. Each profile has per-face textures (top, side, right, forward, left, bottom) with optional normal, displacement and PBR maps.

Setting Up Dual Materials

  1. Create a VoxelMaterialProfile asset (Create > Voxel Play > Voxel Material Profile)
  2. Assign the secondary textures (e.g. grass textures for the top layer)
  3. On the VoxelDefinition, assign the profile to the Secondary Material Profile field
  4. Set the microvoxels layout to Slabs and adjust secondaryTypeHeight

At runtime, the engine creates an internal shadow VoxelDefinition from the profile and uses it for the secondary material zones.

Per-Quad Material Routing

When using palettes, individual cells can override which material is used regardless of the layout mode. This is encoded in the alpha channel of the palette color (bits 7-6):

ModeAlpha bitsBehavior
INHERIT00Use the layout rule (Slabs/TopCap height threshold)
PRIMARY01Force primary material regardless of position
SECONDARY10Force secondary material regardless of position

This enables fine-grained control: a single microvoxel shape can have some cells using grass textures and others using stone, independent of their vertical position.

Creating Microvoxels in the Editor

Select a VoxelDefinition asset and expand the Microvoxels section in the inspector. Available tools:

  • Clear: Remove all microvoxel data
  • Bottom Slab / Top Slab: Fill half the voxel
  • Custom Height: Fill a specific number of layers (0-15)

The inspector shows a 3D preview of the shape (click to rotate) and a layer diagram.

Alternatively, create a standalone MicroVoxelsDefinition asset and reference it from multiple VoxelDefinitions to share shapes.

PBR Surface Maps

VoxelDefinitions support full PBR maps per face. For each face direction (top, side, right, forward, bottom) you can assign:

  • Metallic, Smoothness and Occlusion maps (e.g. textureTopMetallic, textureSideSmoothness, textureBottomOcclusion)
  • Emission maps for self-illuminated surfaces (textureTopEmission, ...)

These separate maps are combined into a single packed surface map for rendering. Use the editor's surface-map packing utility, or pack at runtime with TextureTools.PackSurfaceMap() (see the scripting reference).

Building MicroVoxels from Code

Procedural generators can author MicroVoxels directly: create the object, set occupancy with SetOccupied(x, y, z) (index layout x + z*16 + y*256), and pass it to VoxelPlace(..., microVoxels: mv). Two rules keep this safe:

  • Sharing is managed by the system. The engine clones shared instances before mutating them (copy-on-write), and an instance stored in a second cell is promoted to isShared = true automatically - so multi-cell shapes are safe by default. The flag stays public as an override: set it to true yourself when a single-cell instance must behave as immutable (e.g. a template you keep a reference to), and only force it back to false if you deliberately want in-place mutation of a multi-cell shape.
  • For colored microvoxels, assign the palette before anything captures it. A cell is colored by setting mv.palette (a Color32[]) plus mv.colorIndices (one byte per microvoxel: 0 = no override, k = palette[k-1]). If you build shapes in static initializers, declare the palette field above the builders - C# initializes statics in declaration order and a palette declared below is still null inside them.

Colored microvoxels require Enable Tinting on the environment; the tint multiplies over the definition's texture. Since worlds can mix authored and code-built content, the engine logs a warning at initialization when colored microvoxel definitions exist but tinting is off. Fully occupied cells normally take a fast path that renders them as plain voxels; cells carrying a palette are excluded from it so their colors always render.

See Also

Was this page helpful?