124 lines
5.7 KiB
Markdown
Raw Normal View History

2023-12-08 18:00:41 +08:00
---
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<CW_RGBA, BO_Add, BF_One, BF_InverseSourceAlpha>::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<CW_RGBA, BO_Add, BF_One, BF_One, BO_Add, BF_Zero, BF_One>::GetRHI());
// Disable depth writes as we have a full depth prepass.
DrawRenderState.SetDepthStencilState(TStaticDepthStencilState<false, CF_DepthNearOrEqual>::GetRHI());
}
}
```
设置位置在于FXXXPassMeshProcessor::Process()中的SetDepthStencilStateForBasePass()中。需要bMaskedInEarlyPass为falseGetDepthStencilAccess为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<false, CF_Equal>::GetRHI());
}
```