Coherent GT  1.10.0
A modern user interface library for games
Loading UI textures in advance (preloaded textures)

Texture preloading is a feature of Coherent GT that allows you to manually load and decode textures (which Coherent GT would normally do for you). Texture preloading lets clients to specify content rect where the actual image is. This can be used if the texture has padding or is part of a texture atlas.

This lets you achieve the following use cases:

  • You'd like to improve the loading time of your pages by preparing the textures in advance instead of when Coherent GT asks for them
  • Your game and UI share textures. As a result textures will be read from the disk, decoded and stored in the VRAM twice (by the game and Coherent GT)
  • You'd like to use a custom image format.

Preloading is an advanced feature and requires several steps to get it working.

Note: Coherent GT expects all textures to have premultiplied alpha, keep that in mind when loading your images (unless you replace the default shaders / backends).

  1. Prepare your images

    void PreloadTexture() { for (auto textureURL : texturesToPreload) { preloadedTextures[textureURL] = LoadTexture(textureURL); } }

  2. Override Coherent::UIGT::ResourceHandler::OnResourceRead in your resource handler. Here's a pseudocode implementation:
    void MyResourceHandler::OnResourceRead(const Coherent::UIGT::ResourceRequestUIGT* request,
        Coherent::UIGT::ResourceResponseUIGT* response)
    {
        std::string url = request->GetURL();
        auto texture = preloadedTextures[url];
    
        // This texture isn't loaded yet, let Coherent GT read the raw file.
        if (!texture)
        {
            ReadRawFile(request, response);
            return;
        }
    
        // Tell Coherent GT that the image is preloaded
        using ImageData = Coherent::UIGT::ResourceResponseUIGT::PreloadedImageData;
        ImageData data;
        data.Width = texture->Width;
        data.Height = texture->Height;
        data.ContentRectX = 0;
        data.ContentRectY = 0;
        data.ContentRectWidth = data.Width;
        data.ContentRectHeight = data.Height;
        data.Format = texture->Format;
        data.Texture = texture->Resource;
        response->ReceivePreloadedImage(data);
        response->SignalSuccess();
        response->Release();
    }
    

For example how content rect work check Sample_PreloadedResources.

  1. Modify the rendering backends of your choice to support creating a texture from whatever you passed in your resource handler. Alternatively, your resource handler may return the data in the format used by that backend. See the provided sample and the code for the backends you intend to use.
    void MyBackend::WrapUserTexture(void* userObject,
        const Texture2D& description,
        Texture2DObject object)
    {
        // userObject contains whatever you passed to ResourceResponseUIGT::PreloadedImageData::Texture
        auto textureResource = (MyTextureResource*) userObject;
        // Prepare the texture
    }
    

When the texture is no longer needed, MyBackend::DestroyTexture will be called as it would for any other texture.

See the Sample_PreloadedResources for a demonstration of the technique.

Upgrading from 1.8.6.2

Preloaded images were first introduced in version 1.8.6.2. The original implementation required artists to know in advance whether a resource is preloaded which diminished the flexibility of the feature. The current version allows the decision to preload image to be taken during runtime. The current version has two major changes, breaking the previous API which we introduce to simplify the process and ease the task on artists.

  1. The Coherent::UIGT::ResourceHandler::OnPreloadedResourceRequest method has been removed. Its functionality has been merged in Coherent::UIGT::ResourceHandler::OnResourceRead. This allows you to dynamically decide whether an image is preloaded by calling either Coherent::UIGT::ResourceResponseUIGT::ReceiveData or Coherent::UIGT::ResourceResponseUIGT::ReceivePreloadedImage. By using the latter you declare that image to be preloaded. Calling both on the same response will result in an error.
  2. The preloaded:// protocol has been removed. Use the standard coui:// or don't specify a protocol explicitly in your image URLs.

Emulating the behaviour of versions between 1.8.6.2 and 1.10

If you'd rather have preloaded images tagged as they were previously (preloaded://foo.png) you can emulate it by loading your preloaded resource from coui://preloaded/foo.png and have your ResourceHandler preload all resources that use this address. Note that it's not neccessary for the preloaded directory to actually exist, it may as well be a virtual folder, used merely as a marker for your ResourceHandler for decide whether to use a preloaded resource or not.