--- title: Toon眉毛渲染 date: 2023-12-08 17:48:07 excerpt: tags: rating: ⭐ --- ## 有关眉毛、表情需要使用 模板功能 UTS使用模板 ![[08-Assets/Images/ImageBag/UrealEngineNPR/UTS表情.png]] ![[08-Assets/Images/ImageBag/UrealEngineNPR/UTS表情_StencilOut.png]] ![[08-Assets/Images/ImageBag/UrealEngineNPR/UTS表情_StencilMask.png]] ``` Stencil { Ref[_StencilNo] //设置渲染的模板缓存值,0~255 Comp[_StencilComp] //模板测试的通过条件,有除了equal,还有Greater、Less、Always、Never等,类似ZTest。 Pass[_StencilOpPass] //表示通过模板测试和Z测试(注意是都通过)的像素,怎么处置它的模板值。 Fail[_StencilOpFail] //表示通过了模板测试但没通过Z测试的像素,怎么处置它的模板值。 } _UTS_StencilMode mode = (_UTS_StencilMode)(material.GetInt(ShaderPropStencilMode)); switch (mode) { case _UTS_StencilMode.Off: // material.SetInt(ShaderPropStencilNo,0); material.SetInt(ShaderPropStencilComp, (int)_StencilCompFunction.Disabled); material.SetInt(ShaderPropStencilOpPass, (int)_StencilOperation.Keep); material.SetInt(ShaderPropStencilOpFail, (int)_StencilOperation.Keep); break; case _UTS_StencilMode.StencilMask: // material.SetInt(ShaderPropStencilNo,0); material.SetInt(ShaderPropStencilComp, (int)_StencilCompFunction.Always); material.SetInt(ShaderPropStencilOpPass, (int)_StencilOperation.Replace); material.SetInt(ShaderPropStencilOpFail, (int)_StencilOperation.Replace); break; case _UTS_StencilMode.StencilOut: // material.SetInt(ShaderPropStencilNo,0); material.SetInt(ShaderPropStencilComp, (int)_StencilCompFunction.NotEqual); material.SetInt(ShaderPropStencilOpPass, (int)_StencilOperation.Keep); material.SetInt(ShaderPropStencilOpFail, (int)_StencilOperation.Keep); break; } ``` 七大罪中使用使用了深度测试 Greater Equal.(默认是 less Equal)。但这个方式可能在UE4里不太行,因为UE4的深度测试是全局的? 这个应该需要创建一个MeshProcessor来实现: ```c# FSingleLayerWaterPassMeshProcessor::FSingleLayerWaterPassMeshProcessor(const FScene* Scene, const FSceneView* InViewIfDynamicMeshCommand, const FMeshPassProcessorRenderState& InPassDrawRenderState, FMeshPassDrawListContext* InDrawListContext) : FMeshPassProcessor(Scene, Scene->GetFeatureLevel(), InViewIfDynamicMeshCommand, InDrawListContext) , PassDrawRenderState(InPassDrawRenderState) { if (SingleLayerWaterUsesSimpleShading(Scene->GetShaderPlatform())) { // Force non opaque, pre multiplied alpha, transparent blend mode because water is going to be blended against scene color (no distortion from texture scene color). FRHIBlendState* ForwardSimpleWaterBlendState = TStaticBlendState::GetRHI(); PassDrawRenderState.SetBlendState(ForwardSimpleWaterBlendState); } } //默认是CF_DepthNearOrEqual,做这个效果可能就要使用CF_DepthFartherOrEqual void SetupBasePassState(FExclusiveDepthStencil::Type BasePassDepthStencilAccess, const bool bShaderComplexity, FMeshPassProcessorRenderState& DrawRenderState) { DrawRenderState.SetDepthStencilAccess(BasePassDepthStencilAccess); if (bShaderComplexity) { // Additive blending when shader complexity viewmode is enabled. DrawRenderState.SetBlendState(TStaticBlendState::GetRHI()); // Disable depth writes as we have a full depth prepass. DrawRenderState.SetDepthStencilState(TStaticDepthStencilState::GetRHI()); } } ``` 设置位置在于FXXXPassMeshProcessor::Process()中的SetDepthStencilStateForBasePass()中。需要bMaskedInEarlyPass为false,GetDepthStencilAccess为DepthRead。 ```c# const bool bMaskedInEarlyPass = (MaterialResource.IsMasked() || Mesh.bDitheredLODTransition) && MaskedInEarlyPass(GShaderPlatformForFeatureLevel[FeatureLevel]); if (bEnableReceiveDecalOutput) { // Set stencil value for this draw call // This is effectively extending the GBuffer using the stencil bits const uint8 StencilValue = GET_STENCIL_BIT_MASK(RECEIVE_DECAL, PrimitiveSceneProxy ? !!PrimitiveSceneProxy->ReceivesDecals() : 0x00) | STENCIL_LIGHTING_CHANNELS_MASK(PrimitiveSceneProxy ? PrimitiveSceneProxy->GetLightingChannelStencilValue() : 0x00); if (bMaskedInEarlyPass) { DrawRenderState.SetDepthStencilState(TStaticDepthStencilState< false, CF_Equal, true, CF_Always, SO_Keep, SO_Keep, SO_Replace, false, CF_Always, SO_Keep, SO_Keep, SO_Keep, 0xFF, GET_STENCIL_BIT_MASK(RECEIVE_DECAL, 1) | STENCIL_LIGHTING_CHANNELS_MASK(0x7) >::GetRHI()); DrawRenderState.SetStencilRef(StencilValue); } else if (DrawRenderState.GetDepthStencilAccess() & FExclusiveDepthStencil::DepthWrite) { DrawRenderState.SetDepthStencilState(TStaticDepthStencilState< true, CF_GreaterEqual, true, CF_Always, SO_Keep, SO_Keep, SO_Replace, false, CF_Always, SO_Keep, SO_Keep, SO_Keep, 0xFF, GET_STENCIL_BIT_MASK(RECEIVE_DECAL, 1) | STENCIL_LIGHTING_CHANNELS_MASK(0x7) >::GetRHI()); DrawRenderState.SetStencilRef(StencilValue); } else { DrawRenderState.SetDepthStencilState(TStaticDepthStencilState< false, CF_GreaterEqual, true, CF_Always, SO_Keep, SO_Keep, SO_Replace, false, CF_Always, SO_Keep, SO_Keep, SO_Keep, 0xFF, GET_STENCIL_BIT_MASK(RECEIVE_DECAL, 1) | STENCIL_LIGHTING_CHANNELS_MASK(0x7) >::GetRHI()); DrawRenderState.SetStencilRef(StencilValue); } } else if (bMaskedInEarlyPass) { DrawRenderState.SetDepthStencilState(TStaticDepthStencilState::GetRHI()); } ```