创建并保存Asset通过C++
ue4-create-texture-editor-plugin This example was created for Unreal Engine 4.16. It might not work if the versions are too different.
void CreateTexture() { // Texture Information FString FileName = FString("MyTexture"); int width = 1024; int height = 1024; uint8 * pixels = (uint8 *)malloc(height * width * 4); // x4 because it's RGBA. 4 integers, one for Red, one for Green, one for Blue, one for Alpha
// filling the pixels with dummy data (4 boxes: red, green, blue and white) for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (x < width / 2) { if (y < height / 2) { pixels[y * 4 * width + x * 4 + 0] = 255; // R pixels[y * 4 * width + x * 4 + 1] = 0; // G pixels[y * 4 * width + x * 4 + 2] = 0; // B pixels[y * 4 * width + x * 4 + 3] = 255; // A } else { pixels[y * 4 * width + x * 4 + 0] = 0; // R pixels[y * 4 * width + x * 4 + 1] = 255; // G pixels[y * 4 * width + x * 4 + 2] = 0; // B pixels[y * 4 * width + x * 4 + 3] = 255; // A } } else { if (y < height / 2) { pixels[y * 4 * width + x * 4 + 0] = 0; // R pixels[y * 4 * width + x * 4 + 1] = 0; // G pixels[y * 4 * width + x * 4 + 2] = 255; // B pixels[y * 4 * width + x * 4 + 3] = 255; // A } else { pixels[y * 4 * width + x * 4 + 0] = 255; // R pixels[y * 4 * width + x * 4 + 1] = 255; // G pixels[y * 4 * width + x * 4 + 2] = 255; // B pixels[y * 4 * width + x * 4 + 3] = 255; // A } } } }
// Create Package FString pathPackage = FString("/Game/MyTextures/"); FString absolutePathPackage = FPaths::GameContentDir() + "/MyTextures/";
FPackageName::RegisterMountPoint(*pathPackage, *absolutePathPackage);
UPackage * Package = CreatePackage(nullptr, *pathPackage);
// Create the Texture FName TextureName = MakeUniqueObjectName(Package, UTexture2D::StaticClass(), FName(*FileName)); UTexture2D* Texture = NewObject(Package, TextureName, RF_Public | RF_Standalone);
// Texture Settings Texture->PlatformData = new FTexturePlatformData(); Texture->PlatformData->SizeX = width; Texture->PlatformData->SizeY = height; Texture->PlatformData->PixelFormat = PF_R8G8B8A8;
// Passing the pixels information to the texture FTexture2DMipMap* Mip = new(Texture->PlatformData->Mips) FTexture2DMipMap(); Mip->SizeX = width; Mip->SizeY = height; Mip->BulkData.Lock(LOCK_READ_WRITE); uint8* TextureData = (uint8 *) Mip->BulkData.Realloc(height * width * sizeof(uint8)*4); FMemory::Memcpy(TextureData, pixels, sizeof(uint8) * height * width * 4); Mip->BulkData.Unlock();
// Updating Texture & mark it as unsaved Texture->AddToRoot(); Texture->UpdateResource(); // 这行代码必须调用,否则贴图数据为空。 Package->MarkPackageDirty();
UE_LOG(LogTemp, Log, TEXT( "Texture created: %s" ), &FileName);
free(pixels); pixels = NULL; }
本文的代码是通过拷贝到gVim中,执行 {:%s/^/ /g}命令来批量在每行行首插入空格,然后gg到最开头,大V进入visual模式,G选中到最末尾,确定选中全文后,执行{"+y}拷贝全文到系统粘贴板,最后粘贴到这里。
Asset and Asset File
阅读Assets and Packages一节,我觉得有2个概念需要区分一下:Asset、Asset File。
ENQUEUE压指令到渲染线程获取贴图数据
void GetTexturePixels(FTexture2DRHIRef Texture, TArray<FColor>& OutPixels) { struct FReadSurfaceContext { FTexture2DRHIRef Texture; TArray<FColor>* OutData; FIntRect Rect; FReadSurfaceDataFlags Flags; };
OutPixels.Reset(); FReadSurfaceContext ReadSurfaceContext = { Texture, &OutPixels, FIntRect(0, 0, Texture->GetSizeXY().X, Texture->GetSizeXY().Y), FReadSurfaceDataFlags(RCM_UNorm, CubeFace_MAX) };
ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER( ReadSurfaceCommand, FReadSurfaceContext, Context, ReadSurfaceContext, { RHICmdList.ReadSurfaceData( Context.Texture, Context.Rect, *Context.OutData, Context.Flags ); }); FlushRenderingCommands(); }