UnrealEngne中通过MaterialShader修改GBuffer
前言该篇文档是UE4 插件code方向的一篇分享,目标人群是UE4 Game Player Coder和 Engine Coder和TA中的代码爱好者。
通过该篇文档,你可以:
1. 观察UE4中如何添加HLSL(GlobalShader和MaterialShader)。
2. 观察如何修改UE4的GBuffer管线,定制特殊的功能或者优化。
3. 观察如何结合HLSL和材质蓝图。(类似Volumetric Cloud Material和Lighting Function Material的功能)
同时文中测试代码的UE版本为4.27,需要简单理解UE4渲染管线、材质蓝图和编辑器、插件系统。相关的内容网上很多,这里给出UE4官方链接:
https://docs.unrealengine.com/4.26/en-US/ProgrammingAndScripting/Rendering/ShaderDevelopment/
一.当前存在的问题
当前网络上关于UE4 Shader开发的很多,分析Shader代码的文章不少,但基本上是基于Global Shader来进行讲解。对UE4 Material Shader进行扩展例子在内网、外网暂时没有找到。而通过材质蓝图来修改非物理的效果,应该是一个合理需求。
二.模拟一个需求
现在我们想在UE4计算光照之前,用类似后处理的方式修改所有材质的Roughness或者法线,实现下雨时光滑的效果(但是不想单独在的每个材质球中修改法线和粗糙度),可能后期还会直接修改albedo color等GBuffer信息。
下一步我们需要分析和实现。首先,最好能添加一个插件,不修改或者少修改引擎的代码。其次,插件最好能提供一个类似体积云的Actor或者类似后处理框的Volume,同时能够提供提供一个材质插槽,能够通过材质蓝图来修改目标buffer 。
三.具体的实现
1.添加代码插件。
Shader插件的例子很多,推荐UE4官方文档中GlobalShader的例子,同时可以看下ColorCorrectRegions插件,这个插件通过在管线中插入后处理批次实现需求,很多的需求可以参考此插件,插件路径:
Engine4272\Engine\Plugins\Experimental\ColorCorrectRegions。
2.扩展Render pipeline
很幸运,UE4提供了类FSceneViewExtensionBase
该类原本的目的应该是为了非侵入式的修改RenderPipeline,但很奇怪的是,它的接口没有暴露GraphBuilder。所以我们需要修改引擎,扩展个接口
同时在BasePass结束后调用该接口
到目前为止,引擎的修改已经结束,GBuffer填充的Pipeline已经暴露出来,可以通过扩展ViewExtension修改GBuffer数据。
3.创建GlobalShader修改Gbuffer Normal
这一步我们需要创建临时的RDG rendertarget,拷贝GBufferA(Normal)到TempRT,修改后再写回GBufferA,同时还需要创建一个GlobalShader MainVS(全屏批次),两个GlobalShader PS(Copy和Rewrite),截图如下:
使用到的Gloablshader
FGBufferProcessScreenPassVS通用的全屏Global VS Shader。
FCopyTexturePS拷贝GbufferA Normal到临时RT的Global PS Shader。
FRewritePS采样TempNormalRT并添加测试代码,从新写入GbufferA Normal。
创建临时的RT
通过GlobalShader重新写入Gbuffer
4.将Global PS Shader修改为Material PS Shader,关联材质蓝图
Material PS Shader的使用与Global PS Shader很类似,区别在于创建和设置参数的代码
从FMaterialShader继承出来一个新的PS类
关联一些通用的UniformBuffer,材质蓝图中的一些节点(比如Time节点)转化的ShaderCode会使用这里面的参数。
构建MaterialShader的批次,这个与GlobalShader很类似。
5. 添加MaterialShader的代码
是不是很简单。
流程可以概括为,我们的shader先要包含一个提前生成好的Material.ush,类似GetMaterialEmissive(…)的函数,会在里面进行组装。然后我们要将各种ConstBuffer组装为一个参数集合MaterialParameters,后面给引擎生成的代码函数提供参数。最后就是调用指定Pin脚生成的代码(GetMaterialEmissive),获得材质蓝图对应Shader代码运行的结果。
RenderDoc中截取的Shader代码
6.备注
材质默认使用LightFunction的MaterialDomain,我们可以定义自己的MaterialDomain,或者添加自己的Input、Output节点,相关的代码可以参考VolumetricCloud或者LightFunction的代码。
至此我们完成了所有的编码,Demo代码已上传GitHub,详细的代码请参考Git上代码
https://github.com/Maxwell2012-XC/GBufferProcessPlugin
四.最终的效果
拖一个Actor到场景,然后创建个材质球,让自发光随时间变化
暂用LightFunction的MaterialDomain,可以自行修改和添加新的Domain
关联材质球和修改Gbuffer的Actor
最终的效果
注意左上角的WorldNormal没有修改
注意左上角的WorldNormal已经变化了
下图Actor添加材质后, GbufferNormal已经被修改,随时间变化。场景光照也随之变化。
同理,不限于Normal,Gbuffer其他存储的信息在光照前可以任意修改和定制。(此处希望来脑洞)
Github:
https://github.com/Maxwell2012-XC/GBufferProcessPlugin
期待水友提交完善,如果使用请完善并提交github,遵守许可
参考链接:(同时感谢大佬们分享)
https://docs.unrealengine.com/4.26/en-US/ProgrammingAndScripting/Rendering/ShaderDevelopment/
剖析虚幻渲染体系(08)- Shader体系
剖析虚幻渲染体系(09)- 材质体系
YivanLee:虚幻五渲染编程(Graphic篇)【第二卷:UnrealEngine Shader System Intro】 谢谢分享!!
页:
[1]