2.9.16
Coherent GT
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 (const 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::UserImageData;
        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->ReceiveUserImage(data);
        response->SignalSuccess();
        response->Release();
    }
    
    For example how content rect work check Sample - Preloaded resources.
    Note
    ReadRawFile is called for resources that the application assumes not preloaded.
  3. 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::UserImageData::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 - Preloaded resources for a demonstration of the technique.