找回密码
 立即注册
查看: 325|回复: 1

UnrealEngne中通过MaterialShader修改GBuffer

[复制链接]
发表于 2022-8-21 06:42 | 显示全部楼层 |阅读模式
前言

该篇文档是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】

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
发表于 2022-8-21 06:46 | 显示全部楼层
谢谢分享!!
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-24 13:54 , Processed in 0.090065 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表