5.7 KiB
Raw Blame History

title, date, excerpt, tags, rating
title date excerpt tags rating
Toon眉毛渲染 2023-12-08 17:48:07

有关眉毛、表情需要使用 模板功能

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来实现

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。

	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());
	}