You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将UTextureRenderTarget2D转换为Assimp嵌入式纹理?

问题分析与解决方案

你遇到的核心问题是对Assimp的aiTexture结构使用逻辑理解有误:当设置texture->mHeight = 0时,Assimp将其识别为嵌入式压缩纹理文件(完整的PNG/JPG字节流),此时pcData不需要按aiTexel(RGBA像素格式)解析,直接写入原始压缩字节数据即可。你的代码错误地将压缩后的PNG字节流拆分为RGBA像素填充到aiTexel数组,导致数据格式完全不符合Assimp的预期。

修正步骤

  1. 调整内存分配逻辑:pcData的内存大小应等于压缩后的PNG字节总数,而非按aiTexel的大小计算(压缩后的字节流长度不一定是4的倍数)。
  2. 直接复制原始压缩数据:无需循环拆分RGBA通道,直接将CompressedFile的字节数据拷贝到pcData指向的内存。
  3. 保持格式提示正确:achFormatHint的设置是正确的,保留即可。

修正后的完整代码

static FName ImageWrapperName("ImageWrapper");
IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(ImageWrapperName);

FTextureRenderTargetResource* RTResource = RenderTarget->GameThread_GetRenderTargetResource();
FIntPoint DestSize(RenderTarget->GetSurfaceWidth(), RenderTarget->GetSurfaceHeight());

// 读取RenderTarget像素(这部分逻辑是正确的)
TUniquePtr<TImagePixelData<FColor>> PixelData = MakeUnique<TImagePixelData<FColor>>(DestSize);
PixelData->Pixels.SetNumUninitialized(DestSize.X * DestSize.Y);
RTResource->ReadPixelsPtr(PixelData->Pixels.GetData());

FImageView Image = PixelData->GetImageView();

// 压缩为PNG字节流
TArray64<uint8> CompressedFile;
ImageWrapperModule.CompressImage(CompressedFile, EImageFormat::PNG, Image, (int32)EImageCompressionQuality::Max);

// 初始化Assimp纹理结构
aiTexture* texture = new aiTexture;
texture->mHeight = 0; // 标记为嵌入式压缩文件
texture->mWidth = CompressedFile.Num(); // 压缩数据的总字节数
// 分配足够存储所有压缩字节的内存(注意这里直接用字节数,不是aiTexel数量)
texture->pcData = new aiTexel[CompressedFile.Num()];

// 直接复制原始压缩字节到pcData
memcpy(texture->pcData, CompressedFile.GetData(), CompressedFile.Num());

// 设置格式提示为PNG
texture->achFormatHint[0] = 'p';
texture->achFormatHint[1] = 'n';
texture->achFormatHint[2] = 'g';
texture->achFormatHint[3] = '\0';

scene.mTextures[0] = texture;

额外注意事项

  • 确保在使用完aiTexture后释放内存,避免内存泄漏:delete[] texture->pcData; delete texture;
  • UE的ReadPixelsPtr需要在渲染线程调用,若当前处于游戏线程,建议用ENQUEUE_RENDER_COMMAND包裹读取逻辑,避免线程安全问题:
    ENQUEUE_RENDER_COMMAND(ReadRenderTargetPixels)([&](FRHICommandListImmediate& RHICmdList)
    {
        RTResource->ReadPixelsPtr(PixelData->Pixels.GetData());
    });
    

内容的提问来源于stack exchange,提问作者DigitalBug

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 03:00:58