嗨~~!,熊猫老师又来了 ,这次为大家分享项目中非常实用的一个技术点:遮挡显示。
老规矩,上才艺:
实现原理 :对模型渲染两次。
第一次: 正常渲染物体,深度测试不通过的情况下不会写入模板测试数据,以此来判断遮挡或者没有遮挡部分。
第二次:在后处理之前进行渲染(后处理渲染之后是无法获取模板数据),深度测试不通过,无法渲染相关信息。
具体实现方案
1:在原物体(角色)shader 中 写入深度测试模板:
代码如下:
Stencil
{
Ref 2 //写入模板,数值为2
Comp Always // Gpu 执行所有的像素模板测试
Pass Replace //只要深度测试没有通过,值设成2
Fail Replace //只要深度测试没有通过,值设成2
}
2:创建边缘光效果shader
比较简单,一个Fresnel 效果实现。
half fresnel = saturate(1.0 - dot(normalize(i.normalWS), normalize(i.viewDir));
fresnel = pow(fresnel, _Power);
2:创建renderFeature
如图 一样的操作就可以了
1:Project Settings ———> Quality
双击进入后:
再双击进入后:
创建一个renderFeature
然后照搬我的就可以了:
注意:Layer Mask 需要和物件(角色)保持同一个层里面
为了方便大家测试,我提供了我的两个shader代码:
物件原生shader(角色)
Shader "XiongMaoWuDao/Player"
{
Properties
{
[MainColor] _BaseColor("BaseColor", Color) = (1,1,1,1)
[MainTexture] _BaseMap("BaseMap", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalRenderPipeline" "Queue"="Geometry"}
Stencil
{
Ref 2
Comp Always
Pass Replace
Fail Replace
}
Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
struct Attributes
{
float4 positionOS : POSITION;
float2 uv : TEXCOORD0;
};
struct Varyings
{
float2 uv : TEXCOORD0;
float4 positionHCS : SV_POSITION;
};
TEXTURE2D(_BaseMap);
SAMPLER(sampler_BaseMap);
CBUFFER_START(UnityPerMaterial)
float4 _BaseMap_ST;
half4 _BaseColor;
CBUFFER_END
Varyings vert(Attributes IN)
{
Varyings OUT;
OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz);
OUT.uv = TRANSFORM_TEX(IN.uv, _BaseMap);
return OUT;
}
half4 frag(Varyings IN) : SV_Target
{
return SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, IN.uv) * _BaseColor;
}
ENDHLSL
}
}
}
遮挡后的高亮显示shader :
Shader "XiongMaoWuDao/PlayerLine"
{
Properties
{
_FresnelColor ("Fresnel Color", Color) = (1, 1, 1, 1)
_Power("Power", Range(0.0, 10.0)) = 1
_FresnelIntensity("FresnelIntensity", Range(0.0, 5.0)) = 1
_Cull ("Cull", Int) = 2
}
SubShader
{
Tags { "RenderType"="Transparent" "RenderPipeline"="UniversalRenderPipeline" "Queue"="Transparent"}
Pass
{
Name "XiongMaoWuDao"
Cull[_Cull]
ZTest Always
Blend SrcAlpha OneMinusSrcAlpha
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
struct Attributes
{
float4 positionOS : POSITION;
half3 normalOS : NORMAL;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
half3 normalWS : TEXCOORD0;
half3 viewDir :TEXCOORD1 ;
};
CBUFFER_START(UnityPerMaterial)
half4 _FresnelColor;
half _Power;
half _FresnelIntensity;
CBUFFER_END
//菲尼尔反射
half XionmgMaoWuDao_Fresnel( half3 normal ,half3 viewDir ,half power)
{
//菲尼尔公式: (1-dot (v,n))^power ;
return pow( 1.0- saturate(dot(normal,viewDir).x) ,power);
}
Varyings vert(Attributes v)
{
Varyings o;
o.positionCS = TransformObjectToHClip(v.positionOS.xyz);
o.normalWS = TransformObjectToWorldNormal (v.normalOS );
float3 positionWS = TransformObjectToWorld(v.positionOS.xyz);
o.viewDir =GetWorldSpaceViewDir(positionWS);
return o;
}
half4 frag(Varyings i) : SV_Target
{
half3 normalWS = normalize (i.normalWS);
half3 viewDir = normalize (i.viewDir);
half fresnel = XionmgMaoWuDao_Fresnel(normalWS,viewDir,_Power);
half4 color = _FresnelColor * _FresnelIntensity;
return half4(color.rgb, fresnel);
}
ENDHLSL
}
}
}