UE5 C++ 创建 2D 或 3D 纹理资源

最近在项目里需要在运行时生成体素数据并转换为 3D 纹理资源,过程中踩到不少坑,这里把关键步骤和一份 3D 纹理伪代码整理下来,方便以后查阅。思路同样适用于 2D 纹理,只需把尺寸与 UTexture2D 调整即可。

核心步骤

  1. 创建唯一的包名与资源名:通常用关卡名与 Actor 名组合,避免命名冲突。
  2. 准备像素数据uint8* Data 指向已经排布好的 BGRA 像素缓冲。
  3. 实例化纹理对象:2D 用 UTexture2D,3D 用 UVolumeTexture
  4. 填写 Source 数据并锁定/解锁 Mip:确保字节数与尺寸匹配。
  5. 配置 FTexturePlatformData 与像素格式:例如 PF_B8G8R8A8
  6. 更新资源并标记为脏:调用 UpdateResourcePostEditChangeMarkPackageDirty
  7. 注册到资产库(可选保存为 .uasset)FAssetRegistryModule::AssetCreatedUPackage::SavePackage

3D 纹理伪代码

FString Filename = GetWorld()->GetMapName()+"_"+GetOwner()->GetActorLabel();
const FString PackagePath = FString("/Game/") + Filename;
UPackage* Package = CreatePackage(*PackagePath);
Package->FullyLoad();
uint8* Texture ;
Texture = Data;//Data是要存入的像素数据 uint8指针
//3D纹理
UVolumeTexture* NewTexture3D = NewObject<UVolumeTexture>(Package, *Filename, RF_Public|RF_Standalone|RF_MarkAsRootSet);

// 设置纹理属性
NewTexture3D->Source.Init(SizeX, SizeY, SizeZ, 1, TSF_BGRA8);
NewTexture3D->SRGB = false;
NewTexture3D->Filter = TF_Nearest;
NewTexture3D->CompressionSettings = TC_BC7;
//或者其他自己要设置的属性
uint8* SourceData =  NewTexture3D->Source.LockMip(0);
FMemory::Memcpy(SourceData, Texture,  ByteSize);//ByteSize是算好的大小,字节数
NewTexture3D->Source.UnlockMip(0);

FTexturePlatformData * TexturePlatformData3D =  new FTexturePlatformData();
// 设置贴图大小以及格式
TexturePlatformData3D->SizeX = SizeX;
TexturePlatformData3D->SizeY = SizeY;
TexturePlatformData3D->SetNumSlices(SizeZ);
TexturePlatformData3D->PixelFormat = PF_B8G8R8A8;
NewTexture3D->SetPlatformData(TexturePlatformData3D);
NewTexture3D->AddToRoot();

NewTexture3D->UpdateResource();
NewTexture3D->PostEditChange();
NewTexture3D->MarkPackageDirty();
Package->MarkPackageDirty();
FAssetRegistryModule::AssetCreated(NewTexture3D);

//下面两行是参考的别的人写的,应该可以不写
const FString PackageFileName = FPackageName::LongPackageNameToFilename(PackagePath, FPackageName::GetAssetPackageExtension());
bool bSaved = UPackage::SavePackage(Package, NewTexture3D, EObjectFlags::RF_Public | 
EObjectFlags::RF_Standalone, *PackageFileName, GError, nullptr, true, true, SAVE_NoError);

ByteSize 需根据 SizeX * SizeY * SizeZ * 每像素字节数 计算。若填写错误,LockMip 后的内存拷贝会导致越界或花屏。

注意事项

  • 3D 纹理的 SetNumSlices(SizeZ) 必须与 Source.Init 的 Z 保持一致。
  • 若要生成 2D 纹理,则改用 UTexture2D 并移除 SetNumSlices,同时注意 SizeZ 设为 1。
  • 纹理压缩格式会影响最终效果,TC_BC7 适合高质量 RGBA 数据,若需要线性空间可保持 SRGB = false
  • 若运行时只需内存中的纹理,可跳过 UPackage::SavePackage,但别忘记调用 AddToRoot 以避免 GC。

总结

流程的本质就是:准备好字节数据 → 创建纹理对象 → 写入 Source → 配置 PlatformData → 注册并保存。以上伪代码覆盖了关键 API,按需微调即可快速在 UE5 中生成 2D 或 3D 纹理资源。