UnrealImGui
UnrealImGui copied to clipboard
Dynamic UTexture2D appears white in ImGui
Hello!
I'm trying to display a texture in ImGui that I build at runtime and regularly update in my code. However, any custom transient texture I create that way doesn't seem to be displayed - code doesn't crash, but ImGui only displays a white texture instead of the one I wrote (a yellow test texture).
In essence, here is the code I'm using.
CurrentTexture
is a transient UTexture2D* UPROPERTY on an actor. In BeginPlay
,
CurrentTexture = UTexture2D::CreateTransient(256, 256, EPixelFormat::PF_R8G8B8A8_UINT);
CurrentTexture->UpdateResource();
In Tick, where I'm in the process of writing in my ImGui window:
uint8* Pixels = new uint8[4 * 256 * 256];
for (int32 TextureY = 0; TextureY < 256; ++TextureY)
{
int32 RowOffset = TextureY * 256;
for (int32 TextureX = 0; TextureX < 256; ++TextureX)
{
int32 PixelIndex = RowOffset + TextureX;
// Something more interesting should happen here, but let's say I fill the texture with yellow pixels
Pixels[4 * PixelIndex] = 255;
Pixels[4 * PixelIndex + 1] = 255;
Pixels[4 * PixelIndex + 2] = 0;
Pixels[4 * PixelIndex + 3] = 255;
}
}
// This doesn't seem to be doing anything:
State.CurrentTexture->UpdateTextureRegions(
0,
1,
new FUpdateTextureRegion2D(
0, 0, 0, 0,
256,
256
),
4 * 256,
4,
Pixels,
[](uint8* Data, const FUpdateTextureRegion2D* UpdateRegion)
{
delete UpdateRegion;
delete Data;
});
// This didn't work either (Pixels was then on the stack):
// uint8* TextureData = static_cast<uint8*>(State.CurrentTexture->GetPlatformData()->Mips[0].BulkData.Lock(LOCK_READ_WRITE));
// FMemory::Memcpy(TextureData, Pixels, 4 * sizeof(uint8) * 256 * 256);
// State.CurrentTexture->GetPlatformData()->Mips[0].BulkData.Unlock();
State.CurrentTexture->UpdateResource();
State.ImguiTextureHandle = FImGuiModule::Get().RegisterTexture("WorldDebugMinimap", State.CurrentTexture, false);
// Draw the texture.
ImGui::Image(
State.ImguiTextureHandle,
ImVec2(256, 256));
What am I doing wrong? Am I missing some flags on the UTexture2D? Does it need to be uploaded manually on the GPU? Do I need to call FImGuiModule::RegisterTexture every time I update the texture, or only once (I tried both, and it doesn't change anything). I tried using RenderDoc, and it seems the texture ImGui draws is a 1x1 white texture in my 256x256 ImGui::Image(...) call. I used a breakpoint in the tick, and was seeing the texture containing the right data... so it seems more like a gpu upload issue?
Any help much appreciated <3 The doc is not super clear for playing with textures, and the demo doesn't feature something with a dynamic transient one either.
Thanks in advance! Awesome plugin :)
Found the issue. Seems like the texture format EPixelFormat::PF_R8G8B8A8_UINT is not supported; using EPixelFormat::PF_R8G8B8A8 just works -_-
Would be super nice to see that documented somewhere, and/or fixed :)