如何将 FTexture2DRHIRef 导出为 png?

How to export FTexture2DRHIRef to png?

正如 Unreal Engine 文档在此处提到的 documentation

Textures are images that are used in Materials.They are mapped to the surfaces the Material is applied to.

是否有反向选项,一种将纹理导出到文件(例如.png)的方法?假设我们有FTexture2DRHIRef texture,我们如何获取纹理的原始数据并将其保存在文件中?

Unreal Engine UTexture2D, FRHITexture2D 中还有太多纹理 类 等等。 Unreal Engine 中哪里可以找到关于纹理及其差异的详细解释?

保存纹理到文件当然是选项,但首先你需要知道RHI结构和UTexture对象有什么区别。

Rendering Hardware Interface (RHI) 是独立于平台的高级渲染代码。它为引擎/渲染器的低级平台相关部分提供 [​​=30=]。

我不确定如何正确定义 UTexture,但通常有游戏中使用的对象、编辑器代码、材料等。它们有 RHI 结构的引用。

为了回答您的问题,要将纹理保存到文件中,您应该使用 FFileHelper 结构中的一种方法,即 SaveArrayToFile,作为输入,您需要具有原始纹理数据(或压缩位图 FImageUtils::CompressImageArray),这可能是另一个问题。某些纹理(如 RenderTargets)具有方法 ReadPixels,其中 returns 一个像素数组,但是当您的纹理没有该方法时该怎么办?

您需要深入研究 RHI API 并将一些渲染器命令加入队列,例如:

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();
}

首先,您需要从FTexture2DRHIRef 获取UTexture。我使用此代码从当前游戏视口创建纹理:

 void UScenarioBP_Library::CopyViewportToRenderTarget(UObject* WorldRef, UTextureRenderTarget2D* RenderTarget)
{
    UGameViewportClient* ViewportClient = WorldRef->GetWorld()->GetGameViewport();
    FSceneViewport* Viewport = ViewportClient->GetGameViewport();
    FTexture2DRHIRef Texture = Viewport->GetRenderTargetTexture();
    FRHITexture2D* TextureRHI = Texture->GetTexture2D();

    ENQUEUE_RENDER_COMMAND(ReadSurfaceCommand)(
        [Texture, RenderTarget](FRHICommandListImmediate& RHICmdList)
    {
        FTexture2DRHIRef destTexture = RenderTarget->GetRenderTargetResource()->GetRenderTargetTexture();
        FResolveParams param;
        RHICmdList.CopyToResolveTarget(Texture, destTexture, param);
    });
}