--- title: 自定义材质输出节点 date: 2022-09-02 11:30:37 excerpt: tags: rating: ⭐ --- ## 前言 参考文章:https://zhuanlan.zhihu.com/p/163121357 ## 自定义材质输出节点 继承`UMaterialExpressionCustomOutput`类并实现对应函数即可。 具体可以参考`BentNormal`材质输出节点。Shader代码位于BasePassPixelShader.usf的ApplyBentNormal(),CPP代码位于UMaterialExpressionBentNormalCustomOutput类中(UE4.27)。这种节点会生成`NUM_MATERIAL_OUTPUTS_节点名`的宏。 之后就可以在BasePassPixelShader.usf中通过宏与函数获取到对应的节点计算结果。比如: ```c++ void ApplyBentNormal( in FMaterialPixelParameters MaterialParameters, in float Roughness, inout float3 BentNormal, inout float DiffOcclusion, inout float SpecOcclusion ) { #if NUM_MATERIAL_OUTPUTS_GETBENTNORMAL > 0 #if MATERIAL_TANGENTSPACENORMAL BentNormal = normalize( TransformTangentVectorToWorld( MaterialParameters.TangentToWorld, GetBentNormal0(MaterialParameters) ) ); #else BentNormal = GetBentNormal0(MaterialParameters); #endif FSphericalGaussian HemisphereSG = Hemisphere_ToSphericalGaussian( MaterialParameters.WorldNormal ); FSphericalGaussian NormalSG = ClampedCosine_ToSphericalGaussian( MaterialParameters.WorldNormal ); FSphericalGaussian VisibleSG = BentNormalAO_ToSphericalGaussian( BentNormal, DiffOcclusion ); FSphericalGaussian DiffuseSG = Mul( NormalSG, VisibleSG ); float VisibleCosAngle = sqrt( 1 - DiffOcclusion ); #if 1 // Mix full resolution normal with low res bent normal BentNormal = DiffuseSG.Axis; //DiffOcclusion = saturate( Integral( DiffuseSG ) / Dot( NormalSG, HemisphereSG ) ); DiffOcclusion = saturate( Integral( DiffuseSG ) * 0.42276995 ); #endif float3 N = MaterialParameters.WorldNormal; float3 V = MaterialParameters.CameraVector; SpecOcclusion = DotSpecularSG( Roughness, N, V, VisibleSG ); SpecOcclusion /= DotSpecularSG( Roughness, N, V, HemisphereSG ); SpecOcclusion = saturate( SpecOcclusion ); #endif } ```