So, I use my own way of loading a RAW file into a volume texture.
I take an existing texture, delete all it’s mips, add a new single mip and modify PlatformData so that when I call UpdateResource(), the RHI just takes my bulk data with parameters and creates the resource. I don’t get any errors and I can use my new Volume Texture in a material and it works.
There are two things that happen now and I don’t like them.
a) It’s not persistent between launches. Even if I explicitly press the “Save” button, the next time I fire up my editor, the texture is a 0x0x0, 0 byte texture. From the code and editor I can see that the way we’re expected to make Volume Textures is to import them from Pseudo-Volume slices, but I need to directly load RAW data.
b) The thumbnail in the editor is still showing the previous dimensions. You can see that in the screenshot (but that is just something I noticed and isn’t bothering me that much, unless it has a connection to why it’s not getting properly saved).
I’m hoping I’m just doing something wrong and this isn’t actually a bug…
You can pretty much skip the first half of the following code, as that is handling the opening of the file and checking sizes.
/** Loads a RAW 3D volume (G8 format) into the provided Volume Texture asset. Will output error log messages and return if unsuccessful */
void URaymarchBlueprintLibrary::LoadRawVolumeIntoVolumeTexture(
const UObject* WorldContextObject,
FString textureName, int xDim, int yDim, int zDim, UVolumeTexture* inTexture, UVolumeTexture*& outTexture) {
FIntVector Size(xDim, yDim, zDim);
const int TotalSize = xDim * yDim * yDim;
IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
FString RelativePath = FPaths::ProjectContentDir();
FString FullPath = IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*RelativePath) + textureName;
IFileHandle* FileHandle = PlatformFile.OpenRead(*FullPath);
if (!FileHandle) {
// Or not.
MY_LOG("File could not be opened.");
return;
}
MY_LOG("RAW file was opened!")
if (FileHandle->Size() < TotalSize) {
MY_LOG("File is smaller than expected, cannot read volume.")
return;
} else if (FileHandle->Size() > TotalSize) {
MY_LOG("File is larger than expected, check your dimensions and pixel format (nonfatal, but the texture will probably be screwed up)")
}
// Set volume texture parameters.
inTexture->MipGenSettings = TMGS_NoMipmaps;
inTexture->NeverStream = false;
inTexture->CompressionNone = true;
inTexture->SRGB = false;
// Set PlatformData parameters (create PlatformData if it doesn't exist)
if (!inTexture->PlatformData) {
inTexture->PlatformData = new FTexturePlatformData();
}
inTexture->PlatformData->PixelFormat = PF_G8;
inTexture->PlatformData->SizeX = xDim;
inTexture->PlatformData->SizeY = yDim;
inTexture->PlatformData->NumSlices = zDim;
FTexture2DMipMap* mip = new FTexture2DMipMap();
mip->SizeX = xDim;
mip->SizeY = yDim;
mip->SizeZ = zDim;
mip->BulkData.Lock(LOCK_READ_WRITE);
uint8* ByteArray = (uint8*)mip->BulkData.Realloc(TotalSize);
FileHandle->Read(ByteArray, TotalSize);
mip->BulkData.Unlock();
// Close the RAW file.
delete FileHandle;
// Let the whole world know we were successful.
MY_LOG("File was successfully read!");
// If the texture already has MIPs in it, destroy and free them (Empty() calls destructors and frees space).
if (inTexture->PlatformData->Mips.Num() != 0) {
inTexture->PlatformData->Mips.Empty();
}
// Add the new MIP.
inTexture->PlatformData->Mips.Add(mip);
inTexture->UpdateResource();
return;
}
After this code is run on a “TEST2” Volume Texture asset, the editor looks like this (you can see the still-bad thumbnail)
So, anybody have an idea of what I’m doing wrong in the code / should I load the texture in a different way for it to save?