You've got a streamed world with foliage in it, and something's off. Rocks sit on the ground with a hard line where they meet it. Roads look like decals lying on grass. Cliffs have a seam.

That seam is what Runtime Virtual Textures fix — and the fix comes with a performance win attached.

What RVT actually is

Your landscape material runs per-pixel, every frame, everywhere the landscape is visible. A layered landscape material with six paint layers, slope blending, and distance-based tiling reduction is expensive, and you pay for it constantly.

RVT changes the deal: the landscape material renders into a texture, cached, at a resolution based on how close you are. Now the landscape shader runs when the cache needs updating, not every frame.

And because that texture exists, other meshes can read it. That's the blending. Your rock samples the landscape's colour at its own position and fades into it near the base. No seam.

Setup, in order

Order matters here and getting it wrong produces confusing errors:

  1. Project Settings → Virtual Texture Support → enable. Restart the editor. This isn't optional; virtual texturing won't work until you do.
  2. While you're there: set Auto Virtual Texture Size high if you're not using regular VT for texture samples — otherwise imported textures silently convert to VT and you'll be confused later.
  3. Create a Runtime Virtual Texture asset. Right-click → Materials & Textures → Runtime Virtual Texture. Pick the content type — Base Color, Normal, Roughness, Specular is the common one.
  4. Place a Runtime Virtual Texture Volume in the level. Set its Virtual Texture to your asset. With the volume selected, hit Set Bounds to fit it to the landscape — don't eyeball it.
  5. On the Landscape actor: add your RVT to Draw in Virtual Textures.
  6. In the landscape material: add a Runtime Virtual Texture Output node and feed Base Color / Normal / Roughness / Specular into it.
  7. In the mesh material you want to blend: a Runtime Virtual Texture Sample node, blended against your own texture by height or distance from the mesh base.

If nothing happens, it's almost always step 1 (no restart) or step 4 (bounds wrong).

World Height, and why you need a second volume

If you want height-based blending — rock fades into terrain based on how far above the ground it is — or Virtual Heightfield Mesh, you need a second RVT asset and volume with the World Height content type. Same bounds. This catches people out because the first volume works fine and the height blend silently does nothing.

The 5.6 error you'll probably hit

Migrating a landscape material to 5.6+ throws this at a lot of people:

CB0

Meaning: you're sampling a virtual texture inside the material that writes the RVT output. Circular. The fix is the Runtime Virtual Texture Replace node (sometimes called the VT switch) — it lets the material take one path when rendering into the RVT and another when rendering normally. If you're migrating an older landscape material forward, budget an afternoon for this.

Where it's genuinely worth it

  • Mesh-to-landscape blending. Rocks, cliffs, road splines, building foundations. The single most visible improvement.
  • Expensive landscape materials. Six-layer blend with slope masks? RVT caches it and your GPU stops re-evaluating it every frame.
  • Grass colour matching. Grass samples the landscape RVT and takes its colour from the ground it grows on. Your entire foliage set stops looking pasted on.
  • Roads and paths. A spline mesh writing into the RVT can occlude the grass underneath it. No more grass through tarmac.

Where it isn't

RVT is not free. It's a texture cache: it costs memory, and cache updates cost frames when you move fast across the world. If your landscape material is three layers and simple, and you have no meshes to blend, you're adding a system for nothing. Small maps with simple terrain: skip it.

Common pitfalls

  • Forgetting the editor restart after enabling Virtual Texture Support. Nothing works and there's no obvious message.
  • Bad volume bounds. Use Set Bounds against the landscape. Eyeballed bounds waste resolution on empty air.
  • One volume when you need two. Colour and World Height are separate assets.
  • Not adding the RVT to the Landscape actor's Draw in Virtual Textures list. The material writes nothing.
  • RVT resolution too high. It's memory, and past a point you can't see the difference. Start moderate.
  • Assuming distance blending in the landscape material still works. RVT changes when and where that material evaluates. Distance-based tiling reduction is a classic thing that silently stops behaving.

30-second recap

  • RVT caches your landscape material into a texture, and lets meshes read it.
  • Enable Virtual Texture Support, then restart. This is step zero.
  • RVT asset → RVT Volume with correct bounds → Landscape's Draw in Virtual TexturesRVT Output in landscape material → RVT Sample in mesh material.
  • World Height blending needs a second asset and volume.
  • On 5.6+, sampling VT inside an RVT output errors — use the RVT Replace node.
  • Simple terrain, no blended meshes? Don't bother.

Next Sunday: Instanced Static Meshes — the 10× performance win that's already sitting in your project, and when Nanite makes the whole question moot.

— Marco