虚幻五渲染编程(Graphic篇)【第六卷: Customize GBuffer ...
在Ue5当中拓展GBuffer的时候,我发现UE5的GBuffer的Encode和Decode和Ue4有一点不同,所以我就仔细研究了下UE5的GBuffer的Encode和Decode机制。
GBuffer的Encode和Decode
在UE5中目前会有两套Encode和Decode机制,通过GBUFFER_REFACTOR宏来区隔
第一种是C++生成的Shader来生成Encode和Decode代码
第二种是在Shader里写死的
在FShaderCompileUtilities::ApplyDerivedDefines函数中把GBUFFER_REFACTOR宏塞入
这种通过C++来生成Shader代码的方式问题在于不方便阅读,但好处是非常灵活,可以让C++层来控制Shading。
不方便阅读
GBuffer拓展需要做的事情
如果我们要拓展GBuffer我们需要做几件事情
第一是在C++层要把我们的RT先绑定上去,这件事情需要在CreateSceneTextureUniformBuffer中完成
当然与此同时也需要拓展好FSceneTextureParameters
做完C++层的拓展以后,我们需要拓展C++层和Shader层的DecodeGBuffer和EncodeGBuffer,UE5中需要做好C++方法和Shader写死方法的两个方法的拓展
ShaderGenerationUtil.cpp
我们可以在VS中查看FullStr的值是否符合要求:
DecodeGBufferDataDirect
然后我们就可以开始拓展Shader层了
DeferredShadingCommon.ush
SceneTexturesCommon.ush
最后在LightingPass里就能塞入我们的GBuffer,下面是我的结果:
<hr/>更新:
不知道有没有朋友遇到:“给GBuffer增加了一个数据成员以后就编译不过”的问题:
可是我的GBuffer明明之前有初始化的就是那句 FGBufferData GBuffer = (FGBufferData)0; 这句就是在初始化GBuffer了怎么还会报错呢?
通过我艰苦的寻找Bug我发现如下的代码(下面是我没动过的UE官方原生UE5代码):
我的ToonBufferA这个数据是在这个函数的最后赋值初始化的
这个DecodeGBufferData已经把所有的成员全部重新赋值了一遍了呀,而且出错的地方也不是这样,报错的信息是出在了其它函数身上,但是我怎么改其它函数都不对。
后面经过三天的寻找,我试着把代码改成了下面这样:
问题就解决了。
这说明了几个问题:
1.Epic的代码还是存在漏洞。
2.Epic的Shader代码报错的Output可信度很差,只能作为你修改代码的建议不能作为依据。
3.虚幻的底层Shader开发的确难度过大,这一点UE对比Unity还存在明显差距。
4.假设现在有个Shader的结构体
struct AAA
{
float a;
float b;
float c;
float d;
};如果我们要编写一个Init函数,如果按照虚幻这个bug里的写法就是:
void Init()
{
AAA data;
data.a = 0;
data.b = 0.1;
data.c = 0.2;
data.d = 0.2;
}像上述代码这么写是不保险的,最安全的写法是:
void Init()
{
AAA data = (AAA)0;
data.a = 0;
data.b = 0.1;
data.c = 0.2;
data.d = 0.2;
}
通过虚幻的这个实例,我发现控制Shader的方式还可以通过通知Shader的生成来控制,这个也不失为一个比较好的办法。但是C++写Shader太难阅读了,而且目前UE5.0版本C++部分和Shader写死部分并没有完全解耦,我个人认为这种设计十分失败。
Enjoy it.
todo...
2022/5/29 日黑unity呀 你去看下他写的那个代码,也会想diss他的,真的代码和设计水平太差了。 不愧是大佬,思路清晰。我想做卡渲,多加几个Gbuffer,结果发现太难改,最后还是舍弃一些进度encode到已有gbuffer了
页:
[1]