zoukankan      html  css  js  c++  java
  • UE4 Texture操作总结

    项目中经常需要对texture进行读写操作,所以做个总结。

    方法1:

      

    DynamicTexture = UTexture2D::CreateTransient(SizeX, SizeY);
     
    // Allocate the texture HRI
    DynamicTexture->UpdateResource();
     
    // Use this function to update the texture rects you want to change:
    // NOTE: There is a method called UpdateTextureRegions in UTexture2D but it is compiled WITH_EDITOR and is not marked as ENGINE_API so it cannot be linked from plugins.
     
    void UpdateTextureRegions(UTexture2D* Texture, int32 MipIndex, uint32 NumRegions, FUpdateTextureRegion2D* Regions, uint32 SrcPitch, uint32 SrcBpp, uint8* SrcData, bool bFreeData)
    {
        if (Texture->Resource)
        {
            struct FUpdateTextureRegionsData
            {
                FTexture2DResource* Texture2DResource;
                int32 MipIndex;
                uint32 NumRegions;
                FUpdateTextureRegion2D* Regions;
                uint32 SrcPitch;
                uint32 SrcBpp;
                uint8* SrcData;
            };
     
            FUpdateTextureRegionsData* RegionData = new FUpdateTextureRegionsData;
     
            RegionData->Texture2DResource = (FTexture2DResource*)Texture->Resource;
            RegionData->MipIndex = MipIndex;
            RegionData->NumRegions = NumRegions;
            RegionData->Regions = Regions;
            RegionData->SrcPitch = SrcPitch;
            RegionData->SrcBpp = SrcBpp;
            RegionData->SrcData = SrcData;
     
            ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER(
                UpdateTextureRegionsData,
                FUpdateTextureRegionsData*, RegionData, RegionData,
                bool, bFreeData, bFreeData,
                {
                for (uint32 RegionIndex = 0; RegionIndex < RegionData->NumRegions; ++RegionIndex)
                {
                    int32 CurrentFirstMip = RegionData->Texture2DResource->GetCurrentFirstMip();
                    if (RegionData->MipIndex >= CurrentFirstMip)
                    {
                        RHIUpdateTexture2D(
                            RegionData->Texture2DResource->GetTexture2DRHI(),
                            RegionData->MipIndex - CurrentFirstMip,
                            RegionData->Regions[RegionIndex],
                            RegionData->SrcPitch,
                            RegionData->SrcData
                            + RegionData->Regions[RegionIndex].SrcY * RegionData->SrcPitch
                            + RegionData->Regions[RegionIndex].SrcX * RegionData->SrcBpp
                            );
                    }
                }
                if (bFreeData)
                {
                    FMemory::Free(RegionData->Regions);
                    FMemory::Free(RegionData->SrcData);
                }
                delete RegionData;
            });
        }
    }

    注意需要添加RHI和RenderCore模块,在4.17以后可以直接使用UTexture2D::UpdateTextureRegions。

    方法2:

    Texture = UTexture2D::CreateTransient(SizeX, SizeY);
    FTexture2DMipMap& Mip = [Texture]->PlatformData->Mips[Level];
    void* Data = Mip.BulkData.Lock( LOCK_READ_WRITE );
    FMemory::Memcpy( Data, NewData, DataSize );
    Mip.BulkData.Unlock( );
    Texture->UpdateResource();

    这种方法每次调用都会Lock/UnLock,和updateResource,每次都会删除RHI Texture并重新创建,所以这种做法效率不高,最好不要在Tick等频率高得地方使用。而且UpdateResource只能在主线程中调用。

    判断texture是否初始化用PullTextureTorS->IsValidLowLevel(),重新创建要注意把原有的texture删除。

    PullTextureTorS->ConditionalBeginDestroy();
                    PullTextureTorS = UTexture2D::CreateTransient(width, height, PF_R8G8B8A8);
                    PullTextureTorS->UpdateResource();

    方法3:获取render target的数据

    TArray<FColor> rawData;
    rawData.AddUninitialized(dataSize);
    FTextureRenderTargetResource* renderTarget = tempTexture->GameThread_GetRenderTargetResource();
                renderTarget->ReadPixelsPtr((FColor*)rawData.GetData());
    videoCapture->updateClientData((char *)rawData.GetData(), widht, height);

    上述示例将rendertarget的数据拷贝到rawData,但是要注意ReadPixels这个操作很耗时,相当于把数据从GPU拷贝到CPU,而且会调用FlushingRenderCommand,这个函数会阻塞游戏线程,目前没有在UE4中找到更快的做法,Unity中倒是有将Rendertexture的数据给到一个Texture2D,unity的texture2d可能在CPU中有一份镜像,所以不太耗时。UE4中RHI接口,即RHICommanList中可能会找到如何实现比较快的获取到Rendertarget的数据。

  • 相关阅读:
    UVA 11991 Easy Problem from Rujia Liu(map,vector的使用)
    UVA 11995 I Can Guess the Data Structure! (STL应用)
    HDU 2795 Billboard(线段树,单点更新)
    HDU 1394 Minimum Inversion Number (线段树,单点更新)
    UVA 11827 Maximum GCD(读入技巧,stringstream的使用)
    contest 2 总结
    Const 1 总结
    开始进行大量题目练习
    函数式线段树的个人理解
    poj 2318 TOYS
  • 原文地址:https://www.cnblogs.com/litmin/p/8397959.html
Copyright © 2011-2022 走看看