Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic UTexture2D appears white in ImGui #74

Open
davidtphx opened this issue Oct 5, 2022 · 1 comment
Open

Dynamic UTexture2D appears white in ImGui #74

davidtphx opened this issue Oct 5, 2022 · 1 comment

Comments

@davidtphx
Copy link

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 :)

@davidtphx
Copy link
Author

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 :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant