5.7 KiB
		
	
	
	
	
	
	
	
			
		
		
	
	
			5.7 KiB
		
	
	
	
	
	
	
	
title, date, excerpt, tags, rating
| title | date | excerpt | tags | rating | 
|---|---|---|---|---|
| Toon眉毛渲染 | 2023-12-08 17:48:07 | ⭐ | 
有关眉毛、表情需要使用 模板功能
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来实现:
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。
	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());
	}


