Are there examples anywhere of creating a UTextureCube from an .hdr file at runtime?
The UTexture::Source member is editor only and cannot be used in shipping builds. I’ve got as far as using the FHDRLoadHelper and FDDSLoadHelper classes to get the raw data, but my attempts at populating a dynamically allocated UTextureCube have failed. Typically with a crash down in FTextureCubeResource::GetData as I’ve clearly set things up wrong.
I’ve been able to successfully create UTexture2Ds in a similar fashion leveraging the ImageWrapperModule.
Here is my non-working attempt…
UTextureCube* CreateTransientTextureCube(int32 InSizeX, int32 InSizeY, EPixelFormat InFormat, const FName InName = NAME_None)
{
LLM_SCOPE(ELLMTag::Textures);
UTextureCube* NewTexture = NULL;
if (InSizeX > 0 && InSizeY > 0 &&
(InSizeX % GPixelFormats[InFormat].BlockSizeX) == 0 &&
(InSizeY % GPixelFormats[InFormat].BlockSizeY) == 0)
{
NewTexture = NewObject<UTextureCube>(
GetTransientPackage(),
InName,
RF_Transient
);
NewTexture->PlatformData = new FTexturePlatformData();
NewTexture->PlatformData->SizeX = InSizeX;
NewTexture->PlatformData->SizeY = InSizeY;
NewTexture->PlatformData->PixelFormat = InFormat;
// Allocate first mipmap.
int32 NumBlocksX = InSizeX / GPixelFormats[InFormat].BlockSizeX;
int32 NumBlocksY = InSizeY / GPixelFormats[InFormat].BlockSizeY;
FTexture2DMipMap* Mip = new FTexture2DMipMap();
NewTexture->PlatformData->Mips.Add(Mip);
Mip->SizeX = InSizeX;
Mip->SizeY = InSizeY;
Mip->BulkData.Lock(LOCK_READ_WRITE);
Mip->BulkData.Realloc(NumBlocksX * NumBlocksY * GPixelFormats[InFormat].BlockBytes);
Mip->BulkData.Unlock();
}
else
{
UE_LOG(LogTexture, Warning, TEXT("Invalid parameters specified for CreateTransientTextureCube()"));
}
return NewTexture;
}
UTextureCube* LoadHDR(FString FileName)
{
TArray<uint8> Data;
if (!FFileHelper::LoadFileToArray(Data, *FileName))
{
return nullptr;
}
FHDRLoadHelper HDRLoadHelper(Data.GetData(), Data.GetAllocatedSize());
if (HDRLoadHelper.IsValid())
{
TArray<uint8> DDSFile;
HDRLoadHelper.ExtractDDSInRGBE(DDSFile);
FDDSLoadHelper HDRDDSLoadHelper(DDSFile.GetData(), DDSFile.Num());
//if (HDRDDSLoadHelper.IsValidCubemapTexture())
if (HDRDDSLoadHelper.IsValid2DTexture())
{
int32 Width = HDRDDSLoadHelper.DDSHeader->dwWidth;
int32 Height = HDRDDSLoadHelper.DDSHeader->dwHeight;
EPixelFormat PixelFormat = HDRDDSLoadHelper.ComputePixelFormat();
if (UTextureCube* NewTexture = CreateTransientTextureCube(Width, Height, PixelFormat))
{
uint8* MipData = static_cast<uint8*>(NewTexture->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_WRITE));
// Bulk data was already allocated for the correct size when we called CreateTransient above
FMemory::Memcpy(MipData, HDRDDSLoadHelper.GetDDSDataPointer(), NewTexture->PlatformData->Mips[0].BulkData.GetBulkDataSize());
NewTexture->PlatformData->Mips[0].BulkData.Unlock();
NewTexture->UpdateResource();
return NewTexture;
}
}
}
return nullptr;
}
Any help would be greatly appreciated.
-Randy