(原)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()
{
}
蓝图和资源部分
1、RT (1个对应一个结果)
2、一个UI材质(用于做一些额外效果)
3、一个UI蓝图(就是调用代码和绑定资源,用C++也可以,偷懒下)

RT赋予

BP部分
UI_ShowCapResul_Child:

除了一些我们自己做的方式和LitMode中调试方式
还以通过像素检查器进行分析和查看

题外:
1、Create Custom GBUFFER :http://www.catalinzima.com/xna/tutorials/deferred-rendering-in-xna/creating-the-g-buffer/
2、Buffer,RT ,Pipeline
3、https://en.wikipedia.org/wiki/Deferred_shading
4、高效的GPU GBUFFER管理:http://www.klayge.org/2015/05/25/%E9%AB%98%E6%95%88gpu-buffer%E7%AE%A1%E7%90%86%E4%B9%8Btransient-buffer/

(原)Unreal渲染相关的缓冲区 及其 自定义代码几种抓取的更多相关文章
- (原)Unreal 渲染模块引言Temp
@author:白袍小道 引言 本文只在对Unreal渲染模块做一些详细的理解,务求能分析出个大概. 其中框架的思想和实现的过程,是非常值得学习和推敲一二的. 涉及资源系统,材 ...
- (原)Unreal 渲染模块 渲染流程
@author:白袍小道 浏览分享随缘,评论不喷亦可. 扯淡部分: 在temp中,乱七八糟的说了下大致的UE过程.下面我们还是稍微别那么任性,一步步来吧. UE渲染模块牵扯到场景遍历. ...
- 扩展阿里p3c实现自定义代码规范检查
前段时间fastjson报出了漏洞,只要打开setAutoType特性就会存在风险,自己测试环境的一个项目被揪出来了-_-!.虽然改动很小,但就是觉得憋屈.fastjson还是挺好的,想着禁用的话太 ...
- Java抓取网页数据(原网页+Javascript返回数据)
有时候由于种种原因,我们需要采集某个网站的数据,但由于不同网站对数据的显示方式略有不同! 本文就用Java给大家演示如何抓取网站的数据:(1)抓取原网页数据:(2)抓取网页Javascript返回的数 ...
- 遇到Audio/Speech相关问题,如何抓取log
[DESCRIPTION] 遇到Audio/Speech相关问题时,经常需要抓取相关log信息,总结抓取方法如下 [SOLUTION] 1. 通话声音相关的问题: Case 1: 通话中某一 ...
- IDE MAC下的快捷键,自定义代码块。
快捷键 参考博客:http://blog.csdn.net/iguiyi/article/details/51853728 alt+f7查找在哪里使用 相当于eclipse的ctrl+shift+G ...
- pycharm自定义代码片段
pycharm自定义代码片段 目录 (一)通用阶段 0 .新建.py文件模板:2 0 .pycharm中添加自定义代码片段:一图全知道:3 1 .定义类:classin 描述 ...
- vsCode与Hubilder中自定义代码块
平常测试vue的一些属性时总要新增代码,引入文件,麻烦,顾自定义代码块来实现快速新增测试 一.打开设置 1.1 vsCode设置 点击后选择代码块所属的文件类型,比如在html中则选择html类型配置 ...
- Joomla - 优化(时区、google字体、压缩图片、压缩自定义代码)
Joomla - 优化(时区.google字体.压缩图片.压缩自定义代码) 一.时区 发布文章是往往会发现发布时间和当前时间对不上,原因是 Joomla 用的是国际标准时间,和中国时区大约相差8小时, ...
随机推荐
- IIS配置MIME类型
有时候我们上传的视频,如果IIS上没有配置此格式是播放不了的.这个时候需要你在IIS上添加这个类型才能播放. MIME类型 ①打开你的IIS,点你的网站 ②双击 MIME类型 ③右键-->添加 ...
- js 图片库 改进版
平稳退化 js与html标记分离? 如果有两个函数:firstFunction和secondFunction,如果想让它们俩都在页面加载时得到执行,可以调用函数addLoadEvent,只有一个参数, ...
- 使用泛型实现对int数组或者String数组进行排序
因为是使用的泛型,我们并不确定数据类型, 对于数据的比较就不能用平时的大于或者小于. 我们需要比较对象实现Comparable接口,该接口下的compareTo()方法可以用来比大小 定义Sort类: ...
- 【经典问题】bzoj2957: 楼房重建
经典问题:动态维护上升子序列长度 进阶问题:[经典问题]#176. 栈 Description 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无 ...
- linux下安装xtrabackup
下载需要的版本的xtrabackup软件包,链接如下: https://www.percona.com/downloads/XtraBackup/LATEST/ percona-xtrabackup- ...
- dede后台添加优酷等视频iframe链接时被替换成了图片
添加文章时 添加优酷视频 :<iframe height=498 width=510 src='http://player.youku.com/embed/XNDAzNTAzODE4OA==' ...
- Redis------Set集合类型
set是string类型的无序集合 类比:你的朋友不能超过2的32次方-1个元素 基本添加删除操作 取并集 取交集 取差集 注意:每个元素的各个元素不能重复 应用场合:qq好友推荐‘ TomFri 的 ...
- pytorch中词向量生成的原理
pytorch中的词向量的使用 在pytorch我们使用nn.embedding进行词嵌入的工作. 具体用法就是: import torch word_to_ix={'hello':0,'world' ...
- POJ:2377-Bad Cowtractors
传送门:http://poj.org/problem?id=2377 Bad Cowtractors Time Limit: 1000MS Memory Limit: 65536K Total Sub ...
- [CodeForces948B]Primal Sport(数论)
Description 题目链接 Solution 设f(x)为x的最大质因子 那么由题意易得\(X_1\)的范围在\([X_2-f(X_2)+1,X2]\) 同理\(X_0\)的范围在\([X_1- ...