How to display a UTexture2D via an UImage object?

I use a Widget Switcher as my HUD root widget.
It switches between several Canvas Panels, which contain the actual widgets I want to display.
In one of these canvas panels, I need to display several RenderTargetTextures as well as one Texture2D.
The RenderTargetTextures work fine, they are displayed. However, when I add my Texture2D (whose color I set via code, it is not read from memory), that UImage widget is not displayed.

I have tried to use another RenderTargetTexture instead, which displays the UImage widget, however then I cannot set the pixel colors via code (it is just black).

I have tried both Texture2D and Texture2DDynamic, but both have the same problem, there is no UImage displayed. The texture is however correctly set (for debugging purposes, I chose to set a white color for every pixel and I checked in RenderDoc that the texture is indeed being used, which it is).

Here is the current code I use for adding everything to my Canvas Panel:

UImage* img = NewObject<UImage>(UImage::StaticClass());
img->SetVisibility(ESlateVisibility::Visible);
canvasPanelWidget->AddChild(img);

TArray<UPanelSlot*> slots = canvasPanelWidget->GetSlots();

//the image is at the now last slot
UCanvasPanelSlot* imageSlot = Cast<UCanvasPanelSlot>(slots[slots.Num() - 1]);

imageSlot->SetPosition(FVector2D(0, 0));
imageSlot->SetSize(FVector2D(width, height));  

UTexture2D* headerTexture = UTexture2D::CreateTransient(texSettings.width, texSettings.height, PF_R8G8B8A8_UINT, FName("CPU computed Texture"));
headerTexture->MipGenSettings = TextureMipGenSettings::TMGS_NoMipmaps;
headerTexture->UpdateResource();

 img->SetBrushFromTexture(headerTexture, true);
 img->Brush.DrawAs = ESlateBrushDrawType::Image;
 img->Brush.ImageType = ESlateBrushImageType::FullColor;

What do I have to do, to correctly display an UTexture2D object in an UImage widget?


UPDATE

I have now also tried to use a Material for the brush, which uses a texture sampler and just connect’s that texture sampler’s output to the base color input and nothing else. This works neither with my own texture I created on the fly, nor with a hard coded texture in the material.

I managed to do it after all:

Create a Material that is in the UI domain (I didn’t do this with my update in the question, but it doesn’t work otherwise) and just connect a texture sampler to the base color.

In code, create a UTexture2DDynamic and write to it.
Create a dynamic material instance from that material and set the texture parameter to the dynamic texture you just created.
Call SetBrushFromMaterial on your dynamic material instance. It should now correctly display your CPU written texture.

UImage* img = NewObject<UImage>(UImage::StaticClass());
img->SetVisibility(ESlateVisibility::Visible);

//add img to your root widget and set position and size of the slot as you want it

UTexture2DDynamic* yourTexture = UTexture2DDynamic::Create(width, height);
yourTexture ->MipGenSettings = TextureMipGenSettings::TMGS_NoMipmaps;
yourTexture ->LODGroup = TextureGroup::TEXTUREGROUP_UI;
yourTexture ->UpdateResource();

//guiMaterial is the one you created in the editor with just the texture sampler parameter and a connection to base color
//replace "yourTexture" with whatever you want to use as the outer object, in my case I chose this
UMaterialInstanceDynamic* guiMaterialDynamic = UMaterialInstanceDynamic::Create(guiMaterial, yourTexture);

guiMaterialDynamic->SetTextureParameterValue("Texture", yourTexture );
img->SetBrushFromMaterial(guiMaterialDynamic);

//not sure whether you need these next lines
img->Brush.DrawAs = ESlateBrushDrawType::Box;
img->Brush.ImageType = ESlateBrushImageType::FullColor;
1 Like

One further thing: In my first attempts I set the pixel format to PF_R8G8B8A8_UINT, but creating a Texture2DDynamic it is PF_B8G8R8A8_UINT per default. The change to the former does not seem to work correctly (with the same buffer input).

1 Like