Unreal渲染相关的缓冲区 及其 自定义代码抓取


@authot: 白袍小道

  • 以下为Unreal4.18版本中对GPUBuffer部分的分析结果
  • (插入:比之够着,知至目的)

    ?
    ?

  • Memo of GBuffer (UE4.18)

    ?
    ?

    • GBufferA : Normal(rgb), PerObjectGBufferData(a)

      ?
      ?

    • GBufferB : Metallic(r), Specular(g), Roughness(b), ShadingModelID(a&0xF),

      ?
      ?

    • SelectiveOutputMask(a&0xF0)

      ?
      ?

    • GBufferC : BaseColor(rgb), IndirectIrradiance(a)

      ?
      ?

    • GBufferD : CustomData(rgba)

      ?
      ?

    • GBufferE : PrecomputedShadowFactors(rgba)

      ?
      ?

    • SceneDepth

      ?
      ?

    • CustomNativeDepth : depth?

      ?
      ?

    • CustomStencilTexture

      ?
      ?

    • GBufferVelocity : rgba

      ?
      ?

  • Dbuffer

    ?
    ?

    • DBufferA : PreMultColor(rgb), ColorOpacity(a)

      ?
      ?

    • DBufferB : PreMulWorldNormal(rgb), NormalOpacity(a)

      ?
      ?

    • DBufferC : PreMulRoughness(r ), RoughnessOpacity(g)

    ?
    ?

    (一)、DeferredShadingRender中对Buffer的处理

    从调式和RenderDoc可以详细看到过程,这里就不做详细说明

    ?
    ?

    结果:

    ?
    ?

    (二),代码抓取

    结局:

    https://twitter.com/i/status/1096091562642001920

    这里主要用两种方式去获取,一种是通过Fmemory,一种直接用Unreal提供CopyShareMip

    具体如下:

    ?
    ?

    以下为全部代码:

    ?
    ?

    DynamicAccessGBufferRenderTarget.h:

    //////////////////这里就没有按照Buff处理做分装了,直接怼的(嘿嘿)

    #pragma once

    #include <memory>

    #include "Engine/Texture2D.h"

    #include "Object.h"

    #include "DynamicAccessGBufferRenderTarget.generated.h"

    ?
    ?

    UENUM(BlueprintType)????????????????//"BlueprintType" is essential to include

    enum class EDZShowGbuffer : uint8

    {

    VE_GDZSHOWBUFFERA ????????UMETA(DisplayName = "ShowGBuffA"),

    VE_GDZSHOWBUFFERB ????????UMETA(DisplayName = "ShowGBuffB"),

    VE_GDZSHOWBUFFERC????????UMETA(DisplayName = "ShowGBuffC"),

    VE_GDZSHOWBUFFERD????????UMETA(DisplayName = "ShowGBuffD"),

    VE_GDZSHOWBUFFERE????????UMETA(DisplayName = "ShowGBuffE"),

    };

    ?
    ?

    UENUM(BlueprintType)????????????????//"BlueprintType" is essential to include

    enum class EDZCOPYGbufferType : uint8

    {

    VE_GDZSHOWGBUFFER_COPYMIP ????????UMETA(DisplayName = "COPY_Mip"),

    VE_GDZSHOWBUFFERR_COPYMEMO ????????UMETA(DisplayName = "COPY_Memory"),

    VE_GDZSHOWBUFFERC_CPUARRAY????????UMETA(DisplayName = "COPY_MemoryForWhile"),

    };

    ?
    ?

    USTRUCT()

    struct FCommitRenderData

    {

    GENERATED_BODY()

    public:

    EDZCOPYGbufferType ECOPYBuffType;

    EDZShowGbuffer EShowBuff;

    UTextureRenderTarget2D* mTextureTarget;

    EPixelFormat format;

    int32 canvasWidth = 512;

    int32 canvasHeight = 512;

    bool isGetGBufferData = false;

    };

    ?
    ?

    UCLASS(Blueprintable, BlueprintType)

    class DZRENDERSTUDIOPLUGIN_API UDynamicAccessGBufferRenderTarget : public UObject

    {

    GENERATED_BODY()

    ?
    ?

    public:

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = DynamicAccessGBufferRenderTarget)

    EDZCOPYGbufferType ECOPYBuffType;

    ?
    ?

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = DynamicAccessGBufferRenderTarget)

    EDZShowGbuffer EShowBuff;

    ?
    ?

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = DynamicAccessGBufferRenderTarget)

    UTextureRenderTarget2D* mTextureTarget;

    ?
    ?

    UFUNCTION(BlueprintCallable, Category = DynamicAccessGBufferRenderTarget)

    void InitializeTexture(UTextureRenderTarget2D* pTextureTarget,EDZShowGbuffer pEShowBuff, EDZCOPYGbufferType pECOPYBuffType);

    ?
    ?

    UFUNCTION(BlueprintCallable, Category = DynamicAccessGBufferRenderTarget)

    void CaputerGBuffer();

    ?
    ?

    UFUNCTION(BlueprintCallable, Category = DynamicAccessGBufferRenderTarget)

    void ClearTexture();

    ?
    ?

    UDynamicAccessGBufferRenderTarget();

    ~UDynamicAccessGBufferRenderTarget();

    ?
    ?

    static void CaputerGBufer_Rebuild_RenderThread(FCommitRenderData* pRenderData);

    static void CaputerGBuffer_RenderThread(FCommitRenderData* pRenderData);

    ?
    ?

    static void Copy_TextureRHI(FRHICommandListImmediate& RHICmdList, FRHITexture2D* pDesc, FRHITexture2D* pSrc);

    static void Copy_MemoryRHI(FRHICommandListImmediate& RHICmdList, FRHITexture2D* pDesc, FRHITexture2D* pSrc);

    static void Copy_CPUArrayRHI();

    ?
    ?

    private:

    EPixelFormat format;

    UPROPERTY()

    FCommitRenderData CatchRenderData;

    ?
    ?

    UPROPERTY()

    bool isRebulidRenderTargetSuccess = false;

    };

    ?
    ?

    ?
    ?

    ?
    ?

    DynamicAccessGBufferRenderTarget.cpp

    /**

    * 1、这里步骤基本为先得到当前Buffer的大小,刷新RT目标的数据。并在基础属性变化时* 候再次刷新

    * 2、抓取数据(由于BUFF在Render管线处理时候有获取和释放的处理也是为了能及时释* 放,

    * 所以手动加1,当然成对的写法在DepthRender, Slate等都可以看到,这非常好。

    * 3、CopyShare或者利用FMemory::Memcpy(但拷贝前需要加锁,完成后还需要解锁,所* * 以你懂的

    **/

    ?
    ?

    #include "DynamicAccessGBufferRenderTarget.h"

    #include "private/PostProcess/SceneRenderTargets.h"

    #include "Engine.h"

    #include "RHICommandList.h"

    ?
    ?

    ?
    ?

    ?
    ?

    ?
    ?

    UDynamicAccessGBufferRenderTarget::UDynamicAccessGBufferRenderTarget()

    {

    ?
    ?

    }

    ?
    ?

    UDynamicAccessGBufferRenderTarget::~UDynamicAccessGBufferRenderTarget()

    {

    ?
    ?

    }

    ?
    ?

    void UDynamicAccessGBufferRenderTarget::InitializeTexture(UTextureRenderTarget2D* pTextureTarget, EDZShowGbuffer pEShowBuff, EDZCOPYGbufferType pECOPYBuffType)

    {

    if (mTextureTarget != pTextureTarget || EShowBuff != pEShowBuff || ECOPYBuffType != pECOPYBuffType)

    {

    mTextureTarget = pTextureTarget;

    EShowBuff = pEShowBuff;

    ECOPYBuffType = pECOPYBuffType;

    isRebulidRenderTargetSuccess = false;

    }

    ?
    ?

    }

    ?
    ?

    void UDynamicAccessGBufferRenderTarget::ClearTexture()

    {

    ?
    ?

    }

    ?
    ?

    ?
    ?

    void UDynamicAccessGBufferRenderTarget::CaputerGBuffer()

    {

    if (!CatchRenderData.isGetGBufferData)

    {

    isRebulidRenderTargetSuccess = false;

    CatchRenderData.EShowBuff = EShowBuff;

    CatchRenderData.ECOPYBuffType = ECOPYBuffType;

    CatchRenderData.mTextureTarget = mTextureTarget;

    ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER(

    DZRenderSutioBP_AccessGBufferRenderTarget_init,

    FCommitRenderData*, RenderData, &CatchRenderData,

    {

    UDynamicAccessGBufferRenderTarget::CaputerGBufer_Rebuild_RenderThread(RenderData);

    }

    );

    }

    else

    {

    if (!isRebulidRenderTargetSuccess)

    {

    if (IsInGameThread())

    {

    mTextureTarget->InitCustomFormat(CatchRenderData.canvasWidth, CatchRenderData.canvasHeight, CatchRenderData.format, false);

    mTextureTarget->ForceRebuildPlatformData();

    }

    isRebulidRenderTargetSuccess = true;

    }

    else

    {

    CatchRenderData.EShowBuff = EShowBuff;

    CatchRenderData.ECOPYBuffType = ECOPYBuffType;

    CatchRenderData.mTextureTarget = mTextureTarget;

    ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER(

    DZRenderSutioBP_InterceptSceneGBufferToRenderTarget,

    FCommitRenderData*, RenderData, &CatchRenderData,

    {

    UDynamicAccessGBufferRenderTarget::CaputerGBuffer_RenderThread(RenderData);

    }

    );

    }

    }

    ?
    ?

    }

    ?
    ?

    void UDynamicAccessGBufferRenderTarget::CaputerGBufer_Rebuild_RenderThread(FCommitRenderData* pRenderData)

    {

    FRHICommandListImmediate& RHICmdList = GRHICommandList.GetImmediateCommandList();

    //计数加一避免Render完成后直接清空了GBuffer,但会慢一帧,你猜

    FSceneRenderTargets::Get(RHICmdList).AdjustGBufferRefCount(RHICmdList, 1);

    FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList);

    if (SceneContext.GBufferA)

    {

    FTexture2DRHIRef vTextTarget;

    switch (pRenderData->EShowBuff)

    {

    case EDZShowGbuffer::VE_GDZSHOWBUFFERA:

    vTextTarget = SceneContext.GetGBufferATexture();

    break;

    case EDZShowGbuffer::VE_GDZSHOWBUFFERB:

    vTextTarget = SceneContext.GetGBufferBTexture();

    break;

    case EDZShowGbuffer::VE_GDZSHOWBUFFERC:

    vTextTarget = SceneContext.GetGBufferCTexture();

    break;

    case EDZShowGbuffer::VE_GDZSHOWBUFFERD:

    vTextTarget = SceneContext.GetGBufferDTexture();

    break;

    case EDZShowGbuffer::VE_GDZSHOWBUFFERE:

    vTextTarget = SceneContext.GetGBufferETexture();

    break;

    default:

    vTextTarget = SceneContext.GetGBufferATexture();

    break;

    }

    ?

    pRenderData->format = vTextTarget->GetFormat();

    pRenderData->canvasWidth = vTextTarget->GetSizeX();

    pRenderData->canvasHeight = vTextTarget->GetSizeY();

    pRenderData->isGetGBufferData = true;

    }

    FSceneRenderTargets::Get(RHICmdList).AdjustGBufferRefCount(RHICmdList, -1);

    }

    ?
    ?

    void UDynamicAccessGBufferRenderTarget::CaputerGBuffer_RenderThread(FCommitRenderData* pRenderData)

    {

    FRHICommandListImmediate& RHICmdList = GRHICommandList.GetImmediateCommandList();

    //计数加一避免Render完成后直接清空了GBuffer,但会慢一帧,你猜

    FSceneRenderTargets::Get(RHICmdList).AdjustGBufferRefCount(RHICmdList, 1);

    FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList);

    if (SceneContext.GBufferA && pRenderData->mTextureTarget != nullptr)

    {

    FTexture2DRHIRef vTextTarget;

    switch (pRenderData->EShowBuff)

    {

    case EDZShowGbuffer::VE_GDZSHOWBUFFERA:

    vTextTarget = SceneContext.GetGBufferATexture();

    break;

    case EDZShowGbuffer::VE_GDZSHOWBUFFERB:

    vTextTarget = SceneContext.GetGBufferBTexture();

    break;

    case EDZShowGbuffer::VE_GDZSHOWBUFFERC:

    vTextTarget = SceneContext.GetGBufferCTexture();

    break;

    case EDZShowGbuffer::VE_GDZSHOWBUFFERD:

    vTextTarget = SceneContext.GetGBufferDTexture();

    break;

    case EDZShowGbuffer::VE_GDZSHOWBUFFERE:

    vTextTarget = SceneContext.GetGBufferETexture();

    break;

    break;

    default:

    vTextTarget = SceneContext.GetGBufferATexture();

    break;

    }

    pRenderData->format = vTextTarget->GetFormat();

    if (pRenderData->canvasWidth != vTextTarget->GetSizeX())

    {

    pRenderData->isGetGBufferData = false;

    return;

    }

    FTextureReferenceRHIRef vTexRHIRef = pRenderData->mTextureTarget->TextureReference.TextureReferenceRHI;

    FRHITexture* vRTTexture = vTexRHIRef->GetTextureReference()->GetReferencedTexture();

    FRHITexture2D* vtex = (FRHITexture2D*)vRTTexture;

    if (vtex == nullptr)

    {

    return;

    }

    switch (pRenderData->ECOPYBuffType)

    {

    case EDZCOPYGbufferType::VE_GDZSHOWGBUFFER_COPYMIP:

    UDynamicAccessGBufferRenderTarget::Copy_TextureRHI(RHICmdList,vtex, vTextTarget);

    break;

    case EDZCOPYGbufferType::VE_GDZSHOWBUFFERR_COPYMEMO:

    UDynamicAccessGBufferRenderTarget::Copy_MemoryRHI(RHICmdList, vtex, vTextTarget);

    break;

    case EDZCOPYGbufferType::VE_GDZSHOWBUFFERC_CPUARRAY:

    UDynamicAccessGBufferRenderTarget::Copy_CPUArrayRHI();

    break;

    default:

    break;

    }

    RHICmdList.CopySharedMips(vtex, vTextTarget);

    }

    //移除

    FSceneRenderTargets::Get(RHICmdList).AdjustGBufferRefCount(RHICmdList, -1);

    }

    ?
    ?

    //利用SharedMip的共享方式在这里会快一些

    //扩展方式

    void UDynamicAccessGBufferRenderTarget::Copy_TextureRHI(FRHICommandListImmediate& RHICmdList,FRHITexture2D* pDesc,FRHITexture2D* pSrc)

    {

    RHICmdList.CopySharedMips(pDesc, pSrc);

    }

    ?
    ?

    //内存CPY,但需要锁住,这样就会让另外的渲染不能访问,会造成掉帧率。

    void UDynamicAccessGBufferRenderTarget::Copy_MemoryRHI(FRHICommandListImmediate& RHICmdList, FRHITexture2D* pDesc, FRHITexture2D* pSrc)

    {

    uint32 Lolstrid = 0;

    void * UAVRenderTargetData = RHILockTexture2D(pDesc, 0, RLM_WriteOnly, Lolstrid, true);

    void * UAVCSData = RHILockTexture2D(pSrc, 0, RLM_ReadOnly, Lolstrid, true);

    FMemory::Memcpy(UAVRenderTargetData, UAVCSData, GPixelFormats[pSrc->GetFormat()].BlockBytes * pSrc->GetSizeX() * pSrc->GetSizeY());

    RHICmdList.UnlockTexture2D(pDesc, 0, false);

    RHICmdList.UnlockTexture2D(pSrc, 0, false);

    }

    ?
    ?

    void UDynamicAccessGBufferRenderTarget::Copy_CPUArrayRHI()

    {

    ?
    ?

    }

    ?
    ?

    ?
    ?

原文地址:https://www.cnblogs.com/BaiPao-XD/p/10434648.html

时间: 2024-11-03 23:42:14

Unreal渲染相关的缓冲区 及其 自定义代码抓取的相关文章

c#代码抓取本地QQ号,很实用哦

//抓取QQ号 WebBrowser web = new WebBrowser(); //使用户可以在窗体中导航网页 private void 抓取QQToolStripMenuItem_Click(object sender, EventArgs e) { listView1.Columns.Clear(); listView1.Items.Clear(); listView1.Columns.Add("昵称",100); listView1 .Columns .Add ("

20 行python代码抓取网页中所有JPG图片

#!/usr/bin/python import re import urllib def getHtml(url): page = urllib.urlopen(url) html = page.read() return html def getImg(html): reg = r'src="(.*?\.jpg)" width' imgre = re.compile(reg) imglist = re.findall(imgre, html) num = 0 for imgurl

几行代码抓取百度首页

python中源码位置(以urllib为例):    python中自带的模块:        /usr/lib/python3.5/urllib/request.py(python3)        /usr/lib/python2.7/urllib2.py(python2)    python的第三方模块:        /usr/local/lib/python2.7/site-packages/ 注意:关于urllib模块,python3中的导入方法为import urllib.requ

NetBeans自定义代码折叠块,类似vs中的#region

//<editor-fold defaultstate="collapsed" desc="测试代码折叠"> echo '<script type="text/javascript">'; echo "alert('当前类目下有文章,不能删除!');"; echo "history.go(-1)"; echo "</script>"; exit;//&

vscode自定义代码块

vscode中设置自定义代码块打开首选项,选择用户代码片段,打开后选择编程语言选中后打开文件,按照格式编辑内容 "Print to console log": { "prefix": "csl", "body": [ "console.log('$1')" ], "description": "log output to console" },

Xcode自定义代码块

到现在才发现原来Xcode有自定义代码块这么神奇的功能,能简化很多无聊的敲重复代码的工作,真是感叹我怎么才知道!!! 具体的设置流程见:http://nshipster.cn/xcode-snippets/   或者 http://www.sufeinet.com/thread-8732-1-1.html 然后我也把自己常用的几个写好了放到的github上:   https://github.com/Phelthas/LXMSnippets 使用方法: 将这些.codesnippet文件copy

intelliJ idea自定义代码折叠

原文地址:http://yanwushu.sinaapp.com/intellij-idea_customer_folding_cod/ 在intelliJ idea中不仅可以对类.方法等结构的代码进行折叠(ctrl+-)还可以自定义折叠代码.intelliJ支持两种风格的自定义代码折叠,如下:visual studio style //region Description Your code goes here... //endregion netbeans style // <editor-

ZendStudio自定义代码补全,自定义代码段

很多小伙伴在写代码的时候,肯定会有自己的一些习惯.比如自定义代码段,敲几个键就自动补全自己想要的代码段.省时省力!那么效率你说呢? 本次在ZendStudio中添加自动补全自定义代码段!Eclipse系类软件同理! 好,开干! 通过Windows -> Preference->PHP->Editor->Templates 设置

ZendStudio自定义代码不全,自定义代码段

很多小伙伴在写代码的时候,肯定会有自己的一些习惯.比如自定义代码段,敲几个键就自动补全自己想要的代码段.省时省力!那么效率你说呢? 本次在ZendStudio中添加自动补全自定义代码段!Eclipse系类软件同理! 好,开干! 通过Windows -> Preference->PHP->Editor->Templates 设置