Runtime Virtual Texturing

An overview of Runtime Virtual Textures in Unreal Engine.

Windows
MacOS
Linux

A Runtime Virtual Texture (RVT) creates its texel data on demand using the GPU at runtime, and works similarly to traditional texture mapping. The RVT caches shading data over large areas, making them a good fit for Landscape shading that uses decal-like materials and splines that are well suited to conform to the terrain.

Workflow

Use the following high-level steps to set up and use runtime virtual texturing in your project:

  1. Create a Runtime Virtual Texture Asset(s) in the Content Browser. It is used to link all the components (Actors, RVT Volume, and RVT Materials) together to render the runtime virtual texture.

  2. Add a Runtime Virtual Texture Volume to the scene from the Modes panel. This is used to place the RVT Asset in the scene.

  3. Configure your Materials to write to the RVT Asset.

  4. Configure Materials to ssample from the RVT Asset.

  5. Set up one or more Primitives or Landscape Actors to render to the RVT Asset.

For a step-by-step guide to setting up RVT, see the Runtime Virtual Texturing Quick Start . In this guide, you'll set up a Landscape material and additional scene Actors to work with runtime virtual texturing.

Runtime Virtual Texturing Components

Use the following components to setup and work with runtime virtual textures in your Unreal Engine 4 (UE4) projects.

Runtime Virtual Texture Asset

The Runtime Virtual Texture Asset contains the configuration details that will be used when creating the RVT in the scene. Think of this as the linchpin in the RVT system that connects your Materials and Actors in the scene that are rendered to the RVT.

The RVT Asset is referenced by the following components:

  1. Each Runtime Virtual Texture Volume placed in the scene is assigned a single RVT Asset.

  2. Individual scene Actors are assigned any number of RVT Assets. When they are within the bounds of a volume that uses one of their assigned RVT Assets, they are rendered to the runtime virtual texture.

  3. Before an Actor is rendered to the RVT through the RVT Volume, its Materials must use the Virtual Texture Material Domain or use properly setup RVT Material Expressions.

Create a new RVT Asset from the Content Browser using the right-click context menu or the Add New button. Under the Materials & Textures category, select a Runtime Virtual Texture.

Click image for full size.

Double-click the Asset to open and configure its settings in its own Editor window:

RVT_Asset_Window.png

Use this window to define the size, tile size, and type of Material Attributes supported by the runtime virtual texture.

For details and usage of these settings, see Virtual Texture Settings page.

Asset Actions

From the right-click context menu, you have a couple of actions that can help you manage your RVT Assets in Materials:

RVTContextMenuActions.png

  • Find Materials Using This will find and highlight in the Content Browser all the Materials that reference this RVT Asset.

  • Fix Material Usage provides an automated way to fix all Materials after changing an RVT Asset Material Type. It finds all Materials and Material Functions that contain a Runtime Virtual Texture Sample node which references this RVT Asset. If the Virtual Texture Material Type in the node does not match the Material Type in the RVT Asset, then the Material Type in the node is fixed to match the RVT Asset.

Runtime Virtual Texture Material Types

When setting up your RVT Material, there are four options to choose from:

Mateiral Type

Description

Compressed Format

Base Color

Stores only the base color.

BC1

Base Color, Normal, Roughness, Specular

Stores the base color, normal, roughness, and specular. When compression is enabled, two BC3 textures are used to hold the data. One texture contains base color and the normal X. The other contains roughness, specular, normal Z direction and normal Y.

BC3 + BC3

YCoCg Base Color, Normal, Specular

Stores base color, normal, roughness, and specular. When compression is enabled, three textures are used; a BC3 texture holds the base color encoded in YCoCg format, a BC5 texture holds the normal X and Y, and a BC1 texture holds roughness, specular, and normal Z direction.

BC3 + BC5 + BC1

World Height

Stores a height value.

R16_UNORM

The Base Color, Normal material type available in Unreal Engine 4.23 has been removed. Assets using it are automatically converted to use the Base Color, Normal, Roughness, Specular material type in 4.24.

Runtime Virtual Texture Base Color Storage

The YCoCg Base Color, Normal, Roughness, Specular material type enables a different encoding of the Base Color in the RVT.

By default, the Base Color is stored as RGB and compressed to BC1. This type of encoding can lead to color shifts and banding in the stored data which is most apparent with Base Color data that has smooth gradients. The YCoCg material type helps reduce these types of artifacts. However, using it comes at the cost of 25% extra memory and some additional performance sampling and decoding of the virtual texture data.

Default Base Color Encoding

YCoCg Base Color Encoding

Runtime Virtual Texture Normal Storage

Normals are stored with X and Y values in a BC5 texture, or in the alpha channels of two BC3 textures, giving them the same precision as BC5. The Z direction of the normal is also used to store world space normals.

There are two ways to write a normal to a RVT from a Material Graph:

  • Using a Runtime Virtual Texture Output node

  • Using a standard material output node

When the material writes from a Runtime Virtual Texture Output node, there are no hidden transforms applied to the output. Whatever is input into the node is written to the RVT (with some encoding to store in the texture).

When the material writes from a standard material output node, an implicit transform is applied. Note that in 4.24 this behavior has changed from previous engine versions. Originally, the default behavior when writing to the RVT from a material output node was to transform the output normal into a shared tangent space defined by the orientation of the RVT volume. In 4.24, the default behavior is to transform the normal into world space.

The recommended way to store normals in an RVT is in world space. The use of this common space should allow for better blending behavior when multiple primitives are writing and reading from the RVT.

Runtime Virtual Texture Volume

The Runtime Virtual Texture Volume is used to place the RVT Asset in the scene. This volume should encompass the Actor that it will render to when the Material is set up; generally, this should be a Landscape or surface terrain-like primitive.

Modes_RVTVolume.png

Any primitives sampling from, or writing to, the runtime virtual texture should be inside the bounds of the volume. When placing the RVT Volume, use the Transform from Bounds parameters in the Level Details panel to quickly position and scale the volume to a selected Actor. Typically, this would be something like a Landscape in your scene.

  1. From the Place Actors panel, drag in a Runtime Virtual Texture Volume to the scene.

  2. With the volume selected, use the level Details panel to locate the Transform from Bounds category and use the Source Actor asset selection or the eye dropper to select an Actor in the scene.

  3. Use the Copy Rotation and Copy Bounds buttons to quickly position, scale, and rotate the volume.

Objects that render to the RVT are rendered using an Orthographic projection in the Negative-Z direction of the RVT Volume.

Runtime Virtual Texture Material Expressions

For scene Actors that are assigned an RVT Asset, their Materials must be set up to enable the following actions:

  • Setting the Material Domain to Virtual Texture, which requires no additional setup, and enables the Actor to be written to the RVT in the scene.

  • Adding Material logic that enables write to the RVT Asset enables objects to be composited into the final RVT generated in the scene.

Material Domain: Virtual Texturing

Use the Details panel to set the Material Domain to Virtual Texture to render it to an RVT in the scene:

RVT_1_MaterialDomainVT.png

The Main Material node is used to write to any bound RVT in the scene that uses the same RVT Asset assigned to an RVT Volume and the scene Actor. No additional setup is required to render the Material or Actor to the RVT in the scene.

Writing to and Sampling from the Runtime Virtual Texture

To write to and sample from an RVT in your scene, you must first setup some RVT expressions to handle this for your material:

  • The Runtime Virtual Texture Output expression is used to define a single material that both writes to and samples the virtual texture. Existing material logic should be plugged into this node.

    Mat_RVTOutput.png

  • The Runtime Virtual Texture Sample expression takes in the assigned RVT Asset to sample and outputs that for this material.

    Mat_RVTSample.png

  • The Runtime Virtual Texture Sample Parameter expression works like the Runtime Virtual Texture Sample node but exposes the RVT Asset being sampled as a parameter for Material Instances to override.

    RVTSampleParam.png

    Like other parameters, you can create this node directly or by right-clicking a Runtime Virtual Texture Sample node and selecting Convert to Parameter from the context menu.

    When using a Material Instance to override the RVT Asset, the RVT Asset assigned must match the Material Type set in the Runtime Virtual Texture Sample Param expression's Details panel.

This is an example Landscape material that writes to and samples the bound RVT Asset. It also uses logic to fall back to traditional landscape rendering when a platform doesn't support Virtual Texturing:

Click image for full size.

Additional Material Expressions

Materials are compiled in one of two contexts for use with RVT:

  • To render to the RVT

  • To render to other passes

The Runtime Virtual Texture Replace expression is ideal when wanting part of your material logic to render to the RVT.

Mat_RVTReplace.png

The View Property expression also has a couple of RVT-specific options:

  • The Virtual Texture Output Level node outputs the RVT mip level currently being rendered.

    Mat_ViewPropertyVTOutputLevel.png

  • The Virtual Texture Output Derivative node outputs the X and Y size of world space covered by a single texel of the current virtual texture output.

    Mat_ViewPropertyVTOutputDerivative.png

An example use case of these expressions would be to mimic the use of some distance-based shading in the RVT. Because RVT shading is camera-independent, this type of shading cannot be expressed directly. However, something similar is achievable by making the shading mip level-dependent. The Runtime Virtual Texture Replace node can be used to implement a mip level-dependent shading path only for the Runtime Virtual Texture Output node.

  • The Virtual Texture Feature Switch is useful when setting up material logic to fallback to an alternative path when virtual texturing is not supported.

Scene Actor Output Properties

Any Actor placed in the scene can render to an RVT. The following Actor-types are good candidates:

Ideal Actor Candidates

Non-Ideal Actor Candidates

  • Landscape and Landscape Splines

  • Static Meshes and Instanced Static Meshes

  • Foliage Instances (for decal scattering)*

  • Skeletal Meshes

  • Movable Static Meshes

  • Animated Meshes

Because RVT content is effectively a shading cache, it isn't fully updated on every frame, meaning that the objects rendered to it are expected to have their mobility be Static. Skinned and animated primitives are not good candidates for rendering to an RVT.

Use the Render to Virtual Textures array in the Actor Details panel to specify which RVT Assets it can render to in the scene. An actor can be assigned to multiple RVTs. Rendering to an RVT only happens when the RVT Asset has been assigned to a placed RVT Volume in the scene and once the Actor's Materials have been set up correctly.

Use the sections that follow to further Actor behavior when rendering to an RVT in the scene.

Virtual Texture Pass Type

Use the Virtual Texture Pass Type selection to control how Landscapes and Primitives render for your project with regard to virtual texturing. Sometimes, it's necessary for the Main Pass to change if a Primitive is rendered to an RVT or when the project is required to run on a platform that doesn't support virtual texturing.

These options enable you to control object rendering to an RVT:

RVT_Actor_RVTAsset_PassType.png

Selection

Description

Virtual Texture Only

Never render this Actor in the Main Pass. If there is no RVT in the scene, it will not render at all. This option should be used for items that aren't necessary (such as decal-type materials) when there is no virtual texture support. For example, using a Static Mesh plane with a material outputting to an RVT will write the material like a decal to the RVT landscape material. If a platform or feature level doesn't support virtual texturing, the Static Mesh plane would not render to the Main Pass.

Virtual Texture OR Main Pass

Renders the Actor to either the RVT or the Main Pass, depending on virtual texture support. For example, a Landscape spline rendering a road mesh and material should write to the RVT to apply its material along the spline. However, if there is no valid RVT in the scene or there is no feature level support for virtual texturing, the spline road mesh will still be visible on the Landscape.

Virtual Texture AND Main Pass

Renders the Actor to the RVT and in the Main Pass regardless of virtual texture support. This is ideal for objects (such as a Landscape) that need to both write to and sample from the RVT. For example, a Landscape material that is set up to both write data to the RVT and render the final RVT should always be visible.

It's recommended to disable shadow casting and collision for primitives being rendered to an RVT. These are not automatically disabled.

Setting LOD and Mips

Use the Virtual Texture Advanced rollout properties to control how Actors render to the RVT by setting level of detail (LOD) and culling behavior. Access these parameters from the Actor's level Details panel:

For Primitives in the scene, adjust the following properties:

RVT_Actor_LODSettings.png

Property

Description

Virtual Texture LOD Bias

This sets the LOD to render into the RVT. It is selected automatically based on how much of the virtual texture page the rendered primitive covers. A further bias can be applied using this option. Higher values will force a lower detailed LOD to be used.

Virtual Texture Skip Mips

This is the number of lowest mips in the RVT to skip rendering this primitive. This option removes the cost of rendering into the RVT if it is known that a primitive doesn't need to be rendered beyond some set draw distance.

Virtual Texture Min Coverage

If this value is set, the Virtual Texture Skip Mips parameter is ignored and instead cull (or remove) the primitive from an RVT mip based on its estimated projected size in the mip. This value is in units of pixels but in log space. For example, setting a value of 3 will cull (or remove) a primitive if its projected size is less than 8 pixels.

For Landscapes in your scene, adjust the following properties:

RVT_Actor_Landscape_LODSettings.png

Property

Description

Virtual Texture Num LODs

The number of LODs used to render Landscape components into the RVT. A setting of 0 means that each Landscape component is rendered into the RVT as a single quad. A setting of 0 is optimal for the GPU. Higher values are required if the Landscape Material requires high frequency vertex interpolated data.

Virtual Texture LOD Bias

A bias applied to the selected LOD for rendering to the RVT.

Object Sort Priority

Rendering multiple primitives to the RVT in the scene presents a potential problem for object layer sorting. Since Z-buffering isn't used and the Actor's material can have alpha blending, it means that the sort order may need to be defined.

Use the level Details panel for any selected Actor in the scene to set its Translucency Sort Priority.

RVT_Actor_TranslucenySortPriority.png

All Actors have a default value of 0. Smaller values always render first (or on the bottom layer) and larger ones render last (or on top).

Translucency Sort Priority | Spline: 1 | Decal: 0

Translucency Sort Priority | Spline: 1 | Decal: 2

The render order of Actors with the same value is undefined. If an Actor is missing from the RVT in your scene, check the Translucency Sort Priority first.

Streaming Virtual Texture Build

When an RVT covers a large world with many Actors, rendering to the low resolution mips of the RVT can be a slow operation. Also, in this scenario, world Actors need to be permanently resident to be available to render to low mips that represent distant parts of the world, which can be expensive for memory.

In this situation, it's more efficient to bake and stream the low resolution mips of an RVT. The higher resolution mips can still be rendered at runtime. In this way, a single virtual texture can make the best use of both Streaming Virtual Texturing and Runtime Virtual Texturing approaches.

Enabling SVT with RVT

  1. To add streaming virtual texture support to an RVT, set the number of low mips that you would like to stream.

  2. In the RVT Asset, set the number of low mips that you would like to stream with the Number of low mips to stream to the virtual texture property.

    Click image for full size.

    A higher number low mip value generates a larger streaming virtual texture that will be used at a closer distance to the camera.

  3. Next, you'll need to build the streaming virtual texture. This can be achieved in two ways:

    • Using the Build menu in the Editor Toolbar and selecting the Build Virtual Textures.

      Click image for full size.

      This option builds all virtual textures in the currently opened Level.

    • Using the RVT Volume component and clicking the Build next to the Use Streaming Low Mips in Editor property.

      Build_BuildVTVolume.png

      This option builds only the virtual textures for the selected RVT Volume.

By default, the Editor always renders with runtime generated RVT data and doesn't render with the streaming virtual texture data. This avoids the need to update the streaming virtual texture after each relevant edit.

To render with the streaming virtual texture in the RVT low mips, select the Use Streaming Low Mips in Editor property in the RVT Volume Details panel.

Optimizations, Statistics, and Debugging

Use the following sections to explore ways to optimize and debug runtime virtual texturing in your projects.

Stats

Open the console using the backtick (`) key and enter the following commands to enable their stats information:

Use stat virtualtexturing to give you feedback about the virtual texturing scene for cost in milliseconds (ms) and counters for page tables.

Stat_VirtualTexturing.png

Use stat virtualtexturememory to display relevant memory counters related to the use of virtual texturing in the current scene.

Stat_VirtualTextureMemory.png

Streaming Virtual Texture Low Mips Debugging

To help visualize the distance at which the streaming virtual texture is being used, use the Build Debug button in the RVT Volume Details panel next to the Use Streaming Low Mips in Editor property.

Build_BuildDebugVTVolume.png

This button rebuilds the streaming texture data with a tint so that it's easy to see where the low streaming virtual texture mips are being used.

Memory Pools

The Memory Pool Sizes for virtual texturing are set up in the BaseEngine.ini configuration file. The pools are set up per-texture format group and tile size. Configuration of the pool size is driven by specifying the maximum memory budget for your project. You'll find these settings under the [/Script/Engine.VirtualTexturePoolConfig].

Unreal Engine 4.24 Syntax

When setting up your own values, Tile Size is now defined as a range of sizes. In addition, there is also bAllowSizeScale which defines whether to use the value set on the command r.VT.PoolSizeScale scalability setting to apply to a memory pool.

When setting up your own values, use the following examples as a starting point:

[/Script/Engine.VirtualTexturePoolConfig]
+Pools=(SizeInMegabyte=128, bAllowSizeScale=1, MinTileSize=0, MaxTileSize=9999, Formats=(PF_DXT5, PF_DXT5))
+Pools=(SizeInMegabyte=4, bAllowSizeScale=0, MinTileSize=0, MaxTileSize=9999, Formats=(PF_G16))

In this setup, a 128MB pool is allocated for Base Color, Normal, Roughness, Specular RVTs and a 4MB pool for World Height RVTs.

Unreal Engine 4.23 Syntax

When setting your own values, a good starting configuration is using a tile size of 128 or 256 with a border of 4 texels, like this example:

[/Script/Engine.VirtualTexturePoolConfig]
+Pools=(SizeInMegabyte=36, TileSize=136, Format=PF_DXT1)
+Pools=(SizeInMegabyte=72, TileSize=136, Format=PF_BC5)
+Pools=(SizeInMegabyte=72, TileSize=136, Format=PF_DXT5)
+Pools=(SizeInMegabyte=34, TileSize=264, Format=PF_DXT1)
+Pools=(SizeInMegabyte=68, TileSize=264, Format=PF_BC5)
+Pools=(SizeInMegabyte=68, TileSize=264, Format=PF_DXT5)

This configuration translates to pools of 64x64 128-size tiles, or 32x32 256 size tiles at a cost of approximately 100MB.

Only one of the BC5 and DXT5 pool will be used according to RVT content type.

When configurating virtual texturing physical memory pools, use the stat virtualtexturing command to show dynamic use of the virtual texturing system, including cache loads. Additionally, enter the command r.VT.ListPhysicalPools to dump a lot of information about the virtual texturing system state to the output log.

Debugging

Use the following console variables for debugging virtual texturing in your project:

Console Variable

Description

r.VT.Flush

Use this command to flush all of the physical caches in the Virtual Texturing system. It can be useful when you suspect an issue that could be caused by a bad cache invalidation.

r.VT.MaxUploadsPerFrame

Use this command to set the maximum number of page uploads per-frame (default is 64). It can be useful when you want to throttle the number of Runtime Virtual Texture Tiles being updated in a frame to prevent performance spikes.

Console Variables and Scalability

The following console variables can be tuned per-project and per-platform or scalability level.

Console Variable

Description

r.VT.MaxUploadsPerFrame

The maximum number of virtual texture page uploads per frame. Reducing this can improve performance at the expense of slower visual updates.

r.VT.MaxUploadsPerFrameInEditor

The maximum number of page uploads per frame when in Editor mode. This is independent of the command r.VT.MaxUploadsPerFrame because in the Editor it's better to trade some runtime performance for a cleaner visualization while working.

r.VT.RVT.TileCountBias

This is a bias to apply to the RVT Asset Size in Tiles property. A value of -1 will halve the RVT resolution. A value of 1 will double the RVT resolution.

r.VT.PoolSizeScale

The scale factor to apply to the virtual texture physical pool sizes. A value of less than 1 will reduce the texture pool sizes. This may be necessary on platforms that are more memory constrained.

r.VT.MaxAnisotropy

This is the specific MaxAnisotropy setting for Virtual Texture sampling.

Additional Notes and Limitations

  • Mobile platforms are not currently supported.

  • Sampling a virtual texture from the Vertex Shader stage is possible. However, use this with extreme caution since no virtual texture GPU feedback will be generated by the vertex shader.

Select Skin
Light
Dark

Welcome to the new Unreal Engine 4 Documentation site!

We're working on lots of new features including a feedback system so you can tell us how we are doing. It's not quite ready for use in the wild yet, so head over to the Documentation Feedback forum to tell us about this page or call out any issues you are encountering in the meantime.

We'll be sure to let you know when the new system is up and running.

Post Feedback