ue4.26 base pass宏和lighting pass宏
一,basepass宏
能在母材质面板上设置的宏,为basepass宏,只能影响basepass。
可以用已有的宏MATERIAL_SSR做个试验。
我们通过下面代码可知,MATERIAL_SSR宏对应材质编辑器detail面板上的Screen Space Reflections
在ShadingModels.ush的DefaultLitBxDF中加入测试代码:
//ShadingModels.ush
...
FDirectLighting DefaultLitBxDF( FGBufferData GBuffer, half3 N, half3 V, half3 L, float Falloff, float NoL, FAreaLight AreaLight, FShadowTerms Shadow ) { BxDFContext Context; ... Lighting.Transmission = 0;
//test begin #if MATERIAL_SSR Lighting.Diffuse=float3(0,1,0); #endif //test end return Lighting; }
...
材质编辑器Details面板勾与不勾Screen Space Reflections,效果分别如下:
可见加在ShadingModel函数里的MATERIAL_SSR宏起了作用。
但这是因为我们把材质设成了 “前向透明”(Blend Mode=Translucent,Lighting Mode=Surface ForwardShading),而前向透明是完全在basepass里画的(在basepass里直接调用shadingmodel函数),所以宏MATERIAL_SSR才起作用。
假如我们把Blend Mode改为Opaque,由于Qpaque是在lighting pass里才调的shadingmodel函数,所以宏MATERIAL_SSR不再起作用(当选Opaque时Screen Space Reflections就变灰了),效果如下:
也可以仿照MATERIAL_SSR的代码,写一个自己的宏,比如:
//Material.h ... /** SSR on translucency */ UPROPERTY(EditAnywhere, Category=Translucency, meta=(DisplayName = "Screen Space Reflections")) uint8 bScreenSpaceReflections : 1; //yang chao begin UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = ForwardShading, meta = (DisplayName = "My Test Check")) uint8 bMyTestCheck : 1; //yang chao end ...
//MaterialShared.h ...
virtual bool ShouldDoSSR() const { return false; }
virtual bool IsMyTestCheck() const { return false; }//yang chao add
... ENGINE_API virtual bool ShouldDoSSR() const override; ENGINE_API virtual bool IsMyTestCheck() const override;//yang chao add ...
//MaterialShared.cpp ... bool FMaterialResource::ShouldDoSSR() const { return Material->bScreenSpaceReflections; } bool FMaterialResource::IsMyTestCheck() const { return Material->bMyTestCheck; }//yang chao add ... OutEnvironment.SetDefine(TEXT("MATERIAL_SSR"), ShouldDoSSR() && IsTranslucentBlendMode(GetBlendMode())); OutEnvironment.SetDefine(TEXT("MATERIAL_MY_TEST_CHECK"), IsMyTestCheck());//yang chao add ...
//ShadingModels.ush ... FDirectLighting DefaultLitBxDF( FGBufferData GBuffer, half3 N, half3 V, half3 L, float Falloff, float NoL, FAreaLight AreaLight, FShadowTerms Shadow ) { BxDFContext Context; ... Lighting.Transmission = 0; //test begin #if MATERIAL_MY_TEST_CHECK Lighting.Diffuse=float3(0,1,0); #endif //test end return Lighting; } ...
设为 前向透明 时,勾与不勾My Test Check,效果分别如下:
设为 opaque时,勾与不勾My Test Check,效果分别如下:
可见,还是一样的结论。
也可以不改c++,用custom node实现,在材质设置为 前向半透明 的情况下,开启和关闭MATERIAL_MY_TEST_CHECK宏:
所以,对于 前向半透明 而言,可以不增加新 shading model,而通过base pass宏来实现同样效果。
二,lighting pass宏
如果想让shadingmodel函数里的宏在opaque模式下起作用,需要用lighting pass宏。
例如模仿SUPPORTS_ANISOTROPIC_MATERIALS写一个新的lighting pass宏MY_TEST_CHECK2:
//ShadingModels.ush ... FDirectLighting DefaultLitBxDF( FGBufferData GBuffer, half3 N, half3 V, half3 L, float Falloff, float NoL, FAreaLight AreaLight, FShadowTerms Shadow ) { BxDFContext Context; ... Lighting.Transmission = 0; //test begin #if MY_TEST_CHECK2 Lighting.Diffuse=float3(0,1,0); #endif //test end return Lighting; } ...
运行会触发断点警告:
继续运行,效果如下:
感觉这种lighting pass宏用处不大,因为不能像base pass宏那样逐母材质设置,只能全局设置(比如用view或者指令)。而且会导致变体大量增加(因为lighting pass本身就已经有很多变体)(虽然可在ShouldCompilePermutation函数中作一些剪裁)。
与其用lighting pass宏,还不如新增shading model,或者通过写gbuffer把值传到lighting pass。
----补充:
light pass中这种变体开关(PermutationVector),也可以用于basepass,见:
ue4.26 运行时切换变体 - 知乎 (zhihu.com)