如何将UTextureRenderTarget2D转换为Assimp嵌入式纹理?
问题分析与解决方案
你遇到的核心问题是对Assimp的aiTexture结构使用逻辑理解有误:当设置texture->mHeight = 0时,Assimp将其识别为嵌入式压缩纹理文件(完整的PNG/JPG字节流),此时pcData不需要按aiTexel(RGBA像素格式)解析,直接写入原始压缩字节数据即可。你的代码错误地将压缩后的PNG字节流拆分为RGBA像素填充到aiTexel数组,导致数据格式完全不符合Assimp的预期。
修正步骤
- 调整内存分配逻辑:
pcData的内存大小应等于压缩后的PNG字节总数,而非按aiTexel的大小计算(压缩后的字节流长度不一定是4的倍数)。 - 直接复制原始压缩数据:无需循环拆分RGBA通道,直接将
CompressedFile的字节数据拷贝到pcData指向的内存。 - 保持格式提示正确:
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
相关产品推荐
相关产品推荐

