Gameplay-driven zone painting and procedural scatter.
TerraInk turns gameplay impacts into persistent paint marks on world surfaces,
then promotes those marks into replicated procedural content through ISM, HISM,
PCG, or FastGeo on supported Unreal Engine versions.
Building gameplay-reactive paint at scale runs into the same four pains in every
project. TerraInk ships answers to all four.
Pain 1
Replicating paint is bandwidth-prohibitive
Sending render-target pixels over the wire to keep clients in sync gets expensive
fast. Most teams end up rolling a splat-data replication path. TerraInk ships one:
the server publishes splats via reliable RPC and clients reconstruct the paint
texture locally, so multiplayer state stays cheap.
Pain 2
Paint-driven scatter needs custom plumbing
Tying paint intensity to procedural mesh placement usually means a project-specific
subsystem with its own readback path, tier promotion logic, and per-cell budgeting.
TerraInk includes the scatter manager and three backend paths (ISM, HISM, FastGeo)
with an auto-resolver that picks the right one per tier.
Pain 3
PCG runtime-gen has no gameplay-aware feeder
PCG runtime-gen graphs need an integration that consumes gameplay state and
triggers regeneration when paint promotes a cell. TerraInkPCGBridge is that feeder,
with per-world keying that survives multi-PIE-client sessions and a hook
architecture that keeps the runtime free of PCG dependencies.
Pain 4
FastGeo runtime needs splat-aware placement
UFastGeoContainer's runtime construction path expects per-cell instance data, and
getting splat-aware placement (with Lumen SDF surface gating, deterministic
seeding for replication parity, and PCG scene-writer integration) is non-trivial.
TerraInkFastGeoCompute is the placement compute pipeline on UE 5.8+.
Where this matters most:
multiplayer territory paint, persistent damage and impact stains, biome conversion,
magic corruption and growth, gameplay-driven environmental change. Anywhere player
actions need to *visibly and procedurally* alter the world and stay in sync.
Why TerraInk
TerraInk gives teams a ready-made bridge between gameplay events, surface feedback,
persistent paint data, procedural scatter, and multiplayer replication.
Runtime authoring
Paint becomes game state
Splats are not only visual marks. They drive scatter, persistence, replication,
and runtime systems that need to react to painted zones.
Artist control
Layer and tier assets
Technical artists can author layers, colors, filters, intensity thresholds,
mesh sets, and backend preferences through Unreal-style data assets.
Multiplayer ready
Replicate splats, not pixels
The server publishes splats to clients. Clients rebuild paint and scatter locally,
avoiding replicated render-target data.
Runtime pipeline
The core loop moves from gameplay trace to visual paint, scatter promotion,
and replicated client reconstruction.
1
Gameplay event fires
Footsteps, weapon impacts, ability cues, territory events, or custom triggers
call the painter component.
2
Painter creates a splat
The hit is traced, filtered, converted into an FTerraInkSplat, and written
into the overlapping acceleration-grid cells. Closest-N eviction keeps each
cell populated with the splats most relevant to its own pixels.
3
Paint appears on surfaces
Paintable surfaces sample the global cell-strip splat texture using the supplied
triplanar material function.
4
Scatter tiers promote
Zone-map intensity crosses a threshold and the scatter manager creates instances
using the resolved backend.
5
Clients reconstruct state
Replicated splats are replayed on clients so paint and scatter match server state.
Core features
TerraInk combines material-side painting, CPU splat state, scatter promotion,
PCG integration, and optional FastGeo routing.
Cell-strip splat texture
Visual paint uses one RGBA32F texture where each splat slot stores position,
radius, color, and intensity. Closest-N eviction keeps the splats most relevant
to each cell.
Triplanar sampling
Paint projection is handled in the material function, avoiding unique UV setup
for each paintable mesh.
Scatter tiers
Tiers define thresholds, mesh slots with optional per-mesh material overrides,
quality gates, PCG hooks, VFX, decals, and optional UV paint.
PCG bridge
PCG runtime-gen graphs can consume TerraInk paint state and regenerate when
cells promote.
FastGeo direct path
On UE 5.8+, high-density per-cell scatter can route directly through FastGeo
without graph evaluation.
Per-world bridge state
Bridge modules key state by world to avoid multi-PIE contamination and stale
primitive scene data.
Gameplay event registry
UTerraInkPaintZoneRegistry exposes Blueprint multicast events when actors
enter, leave, or change tier in a painted zone. Direct sample / tier queries
also available for per-tick gameplay logic.
Five-minute workflow
From plugin enabled to first runtime paint marks, the workflow is compact enough
for artists and gameplay engineers to validate quickly.
Building on Lyra?
Skip the five-minute walkthrough and jump to the
Lyra Integration Guide for the exact Build.cs,
ULyraGameplayAbility_RangedWeapon wiring, gameplay tags, and multiplayer
authority pattern.
Step 1
Create a Paint Config
Add one layer, set its SplatVisualColor, then add one
Style entry under the Styles map keyed by a tag
(e.g. Paint.Style.Default). Inside that style, add one scatter tier
with a mesh and ProxyClass = Auto. Set DefaultStyleTag
on the config to the tag you used.
Step 2
Trigger paint from gameplay
The canonical entry point is UTerraInkSubsystem::PaintZoneAtHit(Hit, Radius,
Layer, Intensity) – call it from any C++ or Blueprint (Gameplay
Ability, projectile hit, etc). For prototyping, attach
UTerraInkPainterComponent to your Pawn / PlayerController and fire
its Paint(...) method instead – the component just wraps the
subsystem call.
Step 3 · on by default
Mark surfaces as paintable (optional, on by default)
bAutoAttachSurfaceOnPaint = true is the default; the subsystem
attaches UTerraInkPaintableSurfaceComponent to every actor that
takes a paint hit, on every machine. You only need to wire surfaces manually if
you've turned auto-attach off or want them pre-bound at level start (via
ScanWorldForPaintableSurfaces).
Materials still need a TerraInk material function: drop
MF_TerraInk_ApplyPaint_SDF_Cluster into static-surface materials, or
MF_TerraInk_ApplyPaint_Local into materials on movable / skinned
actors (per-actor CPD storage via UTerraInkDynamicPaintComponent).
Step 4
Press Play and verify
Paint accumulates, tiers promote, and terraink.DumpStats reports cells, splats,
instances, and backend path.
UV paint (optional):
By default paint is sampled via triplanar projection from world XY. If you want
true UV-mapped paint on an environment material, route its BaseColor
through the MF_TerraInk_ApplyPaint_SDF_Cluster material function
shipped in the plugin content. The fastest path: open
M_BasicBlendApplyPaint from TerraInk Content / Materials.
The apply function is already wired in, so you just plug your BaseColor into it
and use that material on your mesh.
Debug tip:
Run terraink.Debug.ShowProxyClass 1 to encode the resolved backend into
per-instance custom data for visualization.
Backend comparison
ProxyClass can be forced or left on Auto so the resolver chooses the most appropriate
path for the tier.
Backend
Best for
Notes
ISM
Small counts and lightweight runtime placement.
Baseline instancing path.
HISM
Larger standard scatter sets, especially with shadows.
Available on UE 5.6, UE 5.7, and UE 5.8+.
FastGeo direct
High-density per-cell scatter where latency matters.
Requires UE 5.8+ runtime construction API.
PCG-routed
Graph-authored scatter rules and complex filtering.
PCG graphs work on UE 5.6+; PCG-to-FastGeo needs UE 5.8+.
Use cases
TerraInk is useful anywhere gameplay needs to visibly and procedurally transform
the world during play. Pick a use case to see a recommended setup.
Select a use case above to see a recommended setup.
Runtime paint that actually drives the world.
TerraInk gives technical artists and gameplay teams a shared runtime system for
persistent paint, procedural scatter, PCG integration, FastGeo routing, and
multiplayer-safe replication.