124 lines
5.7 KiB
Markdown
124 lines
5.7 KiB
Markdown
|
---
|
|||
|
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为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<false, CF_Equal>::GetRHI());
|
|||
|
}
|
|||
|
```
|