2
\$\begingroup\$

Here's my code:

// get RenderTarget2D
static ConstructorHelpers::FObjectFinder<UTextureRenderTarget2D> TargetObj(TEXT("/Game/Textures/RenderTexture"));
// generate a UTexture2D
CameraTexture = TargetObj.Object->ConstructTexture2D(Target->GetOuter(), "mytexture", Target->GetFlags(), 255);
//Turn off Gamma-correction
CameraTexture->SRGB = 0;

//Guarantee no garbage collection by adding it as a root reference
CameraTexture->AddToRoot();

//Update the texture with new variable values.
CameraTexture->UpdateResource();

GetColor(CameraTexture);

...

FLinearColor ANextGenHUD::GetColor(UTexture2D *MyTexture2D)
{
     FColor* FormatedImageData = static_cast<FColor*>(MyTexture2D->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_ONLY));
     for (int32 y = 0; y < MyTexture2D->PlatformData->Mips[0].SizeY; y++)
     {
         for (int32 x = 0; x < MyTexture2D->PlatformData->Mips[0].SizeX; x++)
         {
             int32 curPixelIndex = (y * MyTexture2D->PlatformData->Mips[0].SizeX) + x;
             FColor c = FormatedImageData[curPixelIndex];
             c.A = 255;
             MyTexture2D->PlatformData->Mips[0].BulkData.Unlock();
             return c;
         }
     }
}

This code is a bit messy fo testing purposes, but shoiuld theoretically get me the color of the first pixel. Instead it just gives me a random color the constantly changes as well when I draw it on the HUD.

What am I doing wrong?

\$\endgroup\$
2
\$\begingroup\$

BulkData is platform and format specific. It isn't an array of colors, and it may not be valid at all. If you really want to read the bulk data of the texture, you have to determine the file format (via the PixelFormat in the PlatformData and decode it. You probably don't want to do this.

(You're also unlocking the bulk data inside the loop, but locked it outside the loop, so only the first read is reasonable.)

What you can do instead is (on the render thread), use the RHI to lock the desired mip level of the texture and read that. You'll still have to understand some basic information about the format (such as the number of components per texel), but you won't have to parse the DXT5 compression or whatever other platform specific magic is actually stored in the bulk data:

You can use RHILockTexture2D for this purpose, something like:

FTexture2DResource* Resource = (FTexture2DResource*)MyTexture2D->Resource;
uint32 Stride = 0; // Assigned by RHILockTexture2D.
void* MipData = RHILockTexture2D(
  Resource->GetTexture2DRHI(),
  MipIndex,
  RLM_ReadOnly,
  Stride,
  false);

MipData will point to the color data of the texture, in whatever format is appropriate (e.g., you'll want to cast it to a byte if you have 8-bit component textures, whether or not the bytes are RGBA, ARGB, RGB, et cetera, depend on the format, and so on).

Make sure to use RHIUnlockTexture2D when you are done.

It's also worth noting that this isn't necessarily particularly fast, so it's probably not something you want to be doing every frame if you can avoid it.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.