Preloaded Textures
Textures inside the UI
This feature allows users to efficiently share Unreal textures between the Engine and the UI.
Usually, whenever a texture is needed, Prysm would read it from disk, decode it and upload it to the GPU. There are use cases when this would not be the optimal thing to do. For example:
- The game and the UI share textures (this will result in double processing & memory)
- You don’t want to keep the raw images around, just the imported
.uasset
files.
Unreal textures are static assets that are usually located on disk and before using them, they have to be loaded by the Engine. That incudes reading from disk, decoding and uploading them to the GPU, but once loaded, they will be kept in Unreal’s cache if they are referenced.
The loading of textures happens when Prysm requests them, which normally involves asynchronous loading of the uassets, unless they are preloaded. This will happen when the whole HTML page is parsed and its resources are requested, which includes the Unreal textures and Live Views present in the page declaration. Unreal will not load them into memory in advance when Prysm is initialized.
Once the HTML page is parsed and the UE textures are requested, their loading will be handled by the FStreamableManager class. The FStreamableManager implementation in Unreal Engine could load the texture instantly, in case the .uasset
is already loaded into memory, otherwise it will be streamed from disk.
To use Unreal textures instead of normal images, use the Unreal object paths to reference your images from HTML/CSS, instead of standard URLs, e.g. instead of this:
<img src="foo.png"></img>
use this:
<img src="Texture2D'/Game/uiresources/foo.foo'"></img>
To get the object path for your texture, you can right-click it in the Editor’s Content Browser
and click Copy Reference, then paste the result in your HTML page.
To make sure that there are no visual differences when using Unreal textures, please follow these guidelines:
- Prysm expects images to have premultiplied alpha, Unreal does not. As a result, transparent images will cause the transparent areas to receive a non-transparent color unless premultiplied.
- By default UE stores images in
sRGB
(i.e. it applies gamma-correction). This will result in textures showing darker in some parts. To prevent this issue, make sure that thesRGB
property of the texture asset is checked off. - Make sure you select the proper texture compression for your texture. For example,
DXT
is a lossy format and this may cause artifacts, which may, or may not be acceptable for your use case.
Garbage Collection
kicks in, or memory gets low, and this means the subsequent loads of these textures may be faster, depending on whether the asset is still kept in memory, or not. In order to ensure textures caching, they have to be referenced externally. One way to do that is to use the UCohtmlBaseComponent
and UCohtmlWidget
API, described here.How to import raw images as UTextures
Prysm integration gives you an easy solution to do a bulk import of raw images that will create UTexture2D
assets. These assets are created in a way that should be working as expected with Prysm - the issues with the premultiplied alpha and sRGB
settings, described above, will be automatically solved, ensuring the resulting textures will be looking as expected inside the UI.
To access this feature, all you have to do is select the directory (or directories) in the Unreal Engine Editor’s Content Browser
, right click and under the “Prysm Operations” category select Import Raw Images in Folder
.
Here is an example:
You can also change some of the settings of this functionality in your Prysm options, like the Texture Group
and Compression Settings
of your imported images, as well as if these assets should be automatically saved after being imported. In addition to this, you can modify the Image Extensions
array to include, or exclude certain file extensions that should be considered during importing.
Texture Preloading
For optimal UI loading time, Unreal textures that will be used in the UI should be loaded in advance and kept referenced, to ensure the Engine will keep them cached in memory. The loading of specific textures ahead of time can be done using the provided Prysm integration API, part of the HUD’s UCohtmlBaseComponent
and UCohtmlWidget
:
UCohtmlBaseComponent::PreloadTextureSync
- loads texture from UE object paths synchronously, keeping it referencedUCohtmlBaseComponent::PreloadTextureAsync
- loads texture from UE object paths asynchronously, keeping it referencedUCohtmlBaseComponent::AddPreloadedTexture
- adds a reference to already loaded textureUCohtmlBaseComponent::RemovePreloadedTexture
- removes referenced textureUCohtmlBaseComponent::RemovePreloadedTextureFromPath
- removes referenced texture from UE object pathsUCohtmlBaseComponent::RemoveAllPreloadedTextures
- removes all referenced textures
The functionality listed above is also mirrored in UCohtmlWidget
, and is exposed to Blueprints and available in the TexturePreloading
category. The references for the added textures will be cleared automatically on HUD and Widget destruction.
The example code below shows how to preload textures from a given directory as early as possible in the HUD:
void ACoherentSampleHUD::PreInitializeComponents()
{
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(
FName("AssetRegistry"));
IAssetRegistry& AssetRegistry = AssetRegistryModule.Get();
TArray<FString> PathsToScan;
PathsToScan.Emplace("/Game/uiresources/textures");
AssetRegistry.ScanPathsSynchronous(PathsToScan);
TArray<FAssetData> Assets;
for (auto& Path : PathsToScan)
{
AssetRegistry.GetAssetsByPath(*Path, Assets);
}
auto HUD = GetCohtmlHUD();
for (auto& Item : Assets)
{
// Start preloading textures as early as possible
HUD->PreloadTextureAsync(Item.ObjectPath.ToString());
}
Super::PreInitializeComponents();
}
Lifetime of preloaded resources
Reference flow when using preloaded resources as background-image
:
- Create an element with a style which has preloaded resource for a
background-image
. - When the element’s style is evaluated, the style will add a reference to the resource.
- The reference will be removed when:
- The
background-image
in the element’s style is changed. - The style of the element is removed, or the whole element is removed from the DOM tree.
Lifetime flow in <img>
:
- Create an
<img>
element with a preloaded resource specified by thesrc
attribute. - The element will add a reference to the resource.
- The reference will be removed when:
- The
src
attribute is changed. - The Garbage Collector destroys the element.
How to turn raw image resource paths into preloaded resource paths without doing UI changes
If enabled, the Prysm plugin setting TryLoadUTexturesFromRawImages
will make the integration handle raw image requests as if they were requests for Texture2D
objects and try to load them with priority over the raw images. The Texture2D
objects are expected to be stored in the same location as the raw images.
In case you have already created your UI using raw images, you can easily translate all image URL’s into Texture2D
object paths at runtime. This can help you transition from raw image resources to Texture2D
objects and thus save disk space and memory, without the need of any UI front-end modifications. It may even help you optimize the initial UI loading times, provided that the textures are properly preloaded ahead of time, as described in the sections above.
Texture2D
object, stored in the same location as the original raw image. You should make sure to package the Atlas, or the Texture2D
object in order to load it in the existing game, but you don’t have to package both of them. You also don’t have to package the original raw image, when there is packaged Atlas, or Texture2D
object and TryLoadUTexturesFromRawImages
is turned on.For properly importing images, you can use the Prysm Raw Image Importer tool, as described in the above section.