Hey! I haven’t seen notifications for this in a while! Wow, my post was on 2016!! Time flies!
This is from the engine code, in 5.2. No better reference than the engine itself, especially since it’s made to work on packaged games too.
There’re functions in UKismetRenderingLibrary for reading pixels from UTextureRenderTarget2D and all of them use the same helper function, called ReadRenderTargetHelper. Unfortunately that function is private, declared and defined in a cpp file, so you’ll have to do one of these:
- Use the public static functions from the engine, like
UKismetRenderingLibrary::ReadRenderTarget, which are also Blueprint accessible (bonus). - Copy/paste the code from that helper function. I wouldn’t, since the
UKismetRenderingLibraryfunctions look just fine, passing the pixel values into an array by ref.
It’s important to note that these must be called on the game thread, not the render thread.
If you really want to copy the code from the private function, here goes, without the checks for nullptr and valid sizes and coordinates (don’t forget those!). The function returns the render target pixel format, that’s why there’s the OutFormat variable. If you’re sure of the format you want, you can probably remove a lot of it.
TArray<FColor>& OutLDRValues;
TArray<FLinearColor>& OutHDRValues;
UTextureRenderTarget2D* TextureRenderTarget = /* your texture */;
int32 X; // Give these ints actual values
int32 Y;
int32 Width;
int32 Height;
bool bNormalize = true;
EPixelFormat OutFormat = PF_Unknown;
FTextureRenderTarget2DResource* RTResource = (FTextureRenderTarget2DResource*)TextureRenderTarget->GameThread_GetRenderTargetResource();
FIntRect SampleRect(X, Y, X + Width, Y + Height);
FReadSurfaceDataFlags ReadSurfaceDataFlags = bNormalize ? FReadSurfaceDataFlags() : FReadSurfaceDataFlags(RCM_MinMax);
FRenderTarget* RenderTarget = TextureRenderTarget->GameThread_GetRenderTargetResource();
OutFormat = TextureRenderTarget->GetFormat();
const int32 NumPixelsToRead = Width * Height;
switch (OutFormat)
{
case PF_B8G8R8A8:
if (!RenderTarget->ReadPixels(OutLDRValues, ReadSurfaceDataFlags, SampleRect))
{
OutFormat = PF_Unknown;
}
else
{
check(OutLDRValues.Num() == NumPixelsToRead);
}
break;
case PF_FloatRGBA:
if (!RenderTarget->ReadLinearColorPixels(OutHDRValues, ReadSurfaceDataFlags, SampleRect))
{
OutFormat = PF_Unknown;
}
else
{
check(OutHDRValues.Num() == NumPixelsToRead);
}
break;
default:
OutFormat = PF_Unknown;
break;
}
return OutFormat;