自定义ShadingModel相当于实现了一套自己的默认渲染方式,比如卡通渲染等。当然,重点是这套默认渲染方式,因为他提供了批量化的处理模式,具体怎么理解不妨先把过程走一遍,重点在于如何建立这套模式(这中间的数据传输,逻辑关系)。
这个话题我也是照着网上的一些教材进行学习,其中下列链接比较循规蹈矩,也很细致:
在UE4中创建新的Shading Model_「已注销」的博客-CSDN博客
不过我还要坚持写作的原因是记录我自己踩的坑。
1.什么是ShadingModel?
相比于一上来就讲解怎么做,我更倾向于先知道什么是ShadingMode。所谓ShadingModel,先直接上图:
在UE的材质编辑器中,对于材质的渲染是有很多默认的渲染模式(ShadingModel),使用这种渲染模式就能将材质可视化节点数据按照默认方式进行计算并反馈到材质表现上,个人觉得就是一种工作流(Unity)。那么换句话说,我们要自定义渲染模式,实际就是自动以我们对材质的输入数据如何运作以反馈在材质上。
2.新建渲染模式
UEC++部分:
Step1:新建ShadingModel枚举类型
就好像上方的Default Lit这个渲染模式的类型,就是一个枚举值,那么依葫芦画瓢,我们也来建立我们自定义的渲染模式:MyShadingModel;
找到:Engine\Source\Runtime\Engine\Classes\Engine\EngineTypes.h这个头文件,简单浏览不难发现这里定义了很多方面的引擎类型,比如碰撞,GBuffer等。我们要重点关注的是EMaterialShadingModel这个枚举类型:
enum EMaterialShadingModel
{
MSM_Unlit UMETA(DisplayName="Unlit"),
MSM_DefaultLit UMETA(DisplayName="Default Lit"),
MSM_Subsurface UMETA(DisplayName="Subsurface"),
MSM_PreintegratedSkin UMETA(DisplayName="Preintegrated Skin"),
MSM_ClearCoat UMETA(DisplayName="Clear Coat"),
MSM_SubsurfaceProfile UMETA(DisplayName="Subsurface Profile"),
MSM_TwoSidedFoliage UMETA(DisplayName="Two Sided Foliage"),
MSM_Hair UMETA(DisplayName="Hair"),
MSM_Cloth UMETA(DisplayName="Cloth"),
MSM_Eye UMETA(DisplayName="Eye"),
MSM_SingleLayerWater UMETA(DisplayName="SingleLayerWater"),
MSM_ThinTranslucent UMETA(DisplayName="Thin Translucent"),
//添加自己的ShadingModel
MSM_MyShadingModel UMETA(DisplayName = "MyShadingModel"),
/** Number of unique shading models. */
MSM_NUM UMETA(Hidden),
/** Shading model will be determined by the Material Expression Graph,
by utilizing the 'Shading Model' MaterialAttribute output pin. */
MSM_FromMaterialExpression UMETA(DisplayName="From Material Expression"),
MSM_MAX
};
这里要注意,操作UE的头文件,势必在编译的时候会导致耗费大量时间,特别是这种影响很广的头文件,因此要很细致。(我使用i7 7700实在太难了,编译一次基本4小时起步)
Step2:材质节点Pin激活
对于自定义的ShadingModel往往需要传递一些自定义的数据,那么就要激活材质编辑器的Pin:
找到:Engine\Source\Runtime\Engine\Private\Materials\Material.cpp其中函数为:
static bool IsPropertyActive_Internal(EMaterialProperty InProperty,
EMaterialDomain Domain,
EBlendMode BlendMode,
FMaterialShadingModelField ShadingModels,
ETranslucencyLightingMode TranslucencyLightingMode,
EDecalBlendMode DecalBlendMode,
bool bBlendableOutputAlpha,
bool bHasTessellation,
bool bHasRefraction,
bool bUsesShadingModelFromMaterialExpression)
找到如下代码行:
如此,当ShadingModel为MyShadingModel的时候会激活CustomData0这个Pin,不妨编译一下(考虑时间问题可以暂缓编译)就能看到如下结果:
现在ShadingModel已经能识别我们自定义的枚举MyShadingModel,并且开启了CustomData0这个Pin,但是实际上对材质的操作最后都要落到shader中,那么我们如何通知shader启用我们现在的ShadingModel呢?——答案就是使用C++把一个字符串压入shader里边作为一个宏,那么我们就可以判别宏来使用不同的渲染逻辑了。
上边提供的参考教程中还讲述了怎么隐藏一些Pin,具体方法可以直接从里边获得,当然我为了方便就不叙述,直接上图,注意他这里的TOON_01就等于我们的MyShadingModel:
Engine\Source\Editor\PixelInspector\Private\PixelInspectorResult.h
Engine\Source\Editor\PixelInspector\Private\PixelInspectorResult.cpp:DecodeShadingModel函数
Engine\Source\Editor\PixelInspector\Priv