How to create RenderTextureTarget and save to Content from C++?

Hello Friends,

I’m currently trying to generate some Render Targets on play from ue4 c++ on BeginPlay.
I’ve found you can easily generate textures doing the following:

    //testing on begin play
    int i = 0;		
    //get minimap content game folder from content browser
    		FString TextureName = TEXT("T_MM_T");
    		TextureName += FString::FromInt(i);
    		FString PackageName = TEXT("/Game/Textures/");
    		PackageName += TextureName;
    		UPackage* Package = CreatePackage(NULL, *PackageName);
    		Package->FullyLoad();
    
    		//create texture
    		float TextureWidth = 2048;
    		float TextureHeight = 2048;
    
    		UTexture2D* NewTexture = NewObject<UTexture2D>(Package, *TextureName, RF_Public | RF_Standalone | RF_MarkAsRootSet);
    		NewTexture->AddToRoot();				// This line prevents garbage collection of the texture
    		NewTexture->PlatformData = new FTexturePlatformData();	// Then we initialize the PlatformData
    		NewTexture->PlatformData->SizeX = TextureWidth;
    		NewTexture->PlatformData->SizeY = TextureHeight;
    		NewTexture->PlatformData->NumSlices = 1;
    		NewTexture->PlatformData->PixelFormat = EPixelFormat::PF_FloatRGBA;
    
    		//save texture
    		NewTexture->Source.Init(TextureWidth, TextureHeight, 1, 1, ETextureSourceFormat::TSF_BGRA8);
    		NewTexture->UpdateResource();
    		Package->MarkPackageDirty();
    		FAssetRegistryModule::AssetCreated(NewTexture);
    		FString PackageFileName = FPackageName::LongPackageNameToFilename(PackageName, FPackageName::GetAssetPackageExtension());
    		bool bSaved = UPackage::SavePackage(Package, NewTexture, EObjectFlags::RF_Public | EObjectFlags::RF_Standalone, *PackageFileName, GError, nullptr, true, true, SAVE_NoError);
    		UE_LOG(LogTemp, Warning, TEXT("Generated new texture at %s"), *PackageName);

Now when I try to use this method for UTextureRenderTarget, nothing saves and I get “LogOutputDevice: Error: Class which was marked abstract was trying to be loaded. It will be nulled out on save. RT_MM_RT0 TextureRenderTarget”.

Why does this not work?

UTextureRenderTarget* NewAsset = NewObject<UTextureRenderTarget>(Package, *AssetName, RF_Public | RF_Standalone | RF_MarkAsRootSet);

NewAsset->AddToRoot();				// This line prevents garbage collection of the texture
		NewAsset->CreateResource();

NewAsset->Source.Init(TextureWidth, TextureHeight, 1, 1, ETextureSourceFormat::TSF_BGRA8);
		NewAsset->UpdateResource();

		Package->MarkPackageDirty();
		FAssetRegistryModule::AssetCreated(NewAsset);
		FString PackageFileName = FPackageName::LongPackageNameToFilename(PackageName, FPackageName::GetAssetPackageExtension());
		bool bSaved = UPackage::SavePackage(Package, NewAsset, EObjectFlags::RF_Public | EObjectFlags::RF_Standalone, *PackageFileName, GError, nullptr, true, true, SAVE_NoError);
		UE_LOG(LogTemp, Warning, TEXT("Generated new texture at %s"), *PackageName);

Does anyone have advice for generating TextureRenderTargets from ue4 c++?

Thank you for your time!

Same problem here, have you found a solution?

I got two things to try.

First try creating a texture asset in the editor, then modifying it and saving it to see if that works.

Second UTextureRenderTarget is an abstract class meaning it has to be subclassed to be used as an UObject (I think?) might be wrong about that.

You can see the UMeta here https://github.com/EpicGames/UnrealEngine/blob/c3caf7b6bf12ae4c8e09b606f10a09776b4d1f38/Engine/Source/Runtime/Engine/Classes/Engine/TextureRenderTarget.h

Try using UTextureRenderTarget2D and see if that works for you, it’s not marked abstract

https://github.com/EpicGames/UnrealEngine/blob/46544fa5e0aa9e6740c19b44b0628b72e7bbd5ce/Engine/Source/Runtime/Engine/Classes/Engine/TextureRenderTarget2D.h

1 Like

Continuing the discussion from How to create RenderTextureTarget and save to Content from C++?:

After much trial and error, I successfully created RenderTargetCube and saved to Content Browser using C++

Reference:

My code:

        // The code seems to require UnrealEd and AssetRegistry dependencies
	FString PackageName = TEXT("/Game/**Your_Path**/");
	FStrin BaseName = TEXT("RenderTargetCube_");
	FString Name = BaseName += FString::FromInt(**YourActor**->GetUniqueID());

	FString PackagePath = PackageName + Name;

	UPackage* Package = CreatePackage(nullptr, *PackagePath);
	UTextureRenderTargetCube* RenderTargetCube = NewObject<UTextureRenderTargetCube>(Package,
		UTextureRenderTargetCube::StaticClass(),
		*Name,
		EObjectFlags::RF_Public | EObjectFlags::RF_Standalone);

	// Here You can set RenderTargetCube info

	FAssetRegistryModule::AssetCreated(RenderTargetCube);
	RenderTargetCube->MarkPackageDirty();
	RenderTargetCube->PostEditChange();

Hope this information can help those who are looking for it

1 Like