最近刚好用上了这个效果所以记录一下,原理不再赘述,通过之前的透明原理和渲染队列详解就可以了解。遮挡透视可以区分为两部分,第一部分未被遮挡的顶点则正常栅格化着色,第二部分被遮挡的顶点则Ztest Greater(也就是判断当前顶点depth更大距离相机更远则栅格化着色),下面实现shader代码:
Shader "Unlit/OutrayShader"
{
Properties
{
_OutlineColor("Outline Color",color) = (1,1,1,1)
_RayColor("Ray Color",color) = (1,1,1,1)
_OutScale("Outline Scale",Range(1,2)) = 1
_RayScale("Ray Scale",Range(1,2)) = 1
}
SubShader
{
Tags { "RenderType"="Opaque" "Queue"="Transparent" }
LOD 100
//正常渲染的outline
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 vertex : SV_POSITION;
};
float4 _OutlineColor; /*外描边颜色*/
float _OutScale;
//缩放矩阵
static float4x4 _mats = float4x4(
_OutScale, 0, 0, 0,
0, _OutScale, 0, 0,
0, 0, _OutScale, 0,
0, 0, 0, 1
);
v2f vert(appdata v)
{
v2f o;
//顶点缩放
float4 vs = mul(_mats, v.vertex);
o.vertex = UnityObjectToClipPos(vs);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
return _OutlineColor;
}
ENDCG
}
//透视着色
Pass
{
//ztest greater时则渲染,也就是depth更大透视渲染
ZTest Greater ZWrite off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 vertex : SV_POSITION;
};
float4 _RayColor; /*透视颜色*/
float _RayScale;
static float4x4 _mats = float4x4(
_RayScale, 0, 0, 0,
0, _RayScale, 0, 0,
0, 0, _RayScale, 0,
0, 0, 0, 1
);
v2f vert(appdata v)
{
v2f o;
//顶点缩放
float4 vs = mul(_mats, v.vertex);
o.vertex = UnityObjectToClipPos(vs);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
return _RayColor;
}
ENDCG
}
}
}
效果如下:
可以看得出来正常渲染红色,透视渲染绿色。
当然了一般情况下我们的透视shader属于辅助着色功能,是在不影响原来美术调整好的着色效果情况下实现的第二层材质渲染,所以还得改一下,如下:
Shader "Custom/TransparencyShader"
{
Properties
{
_RayColor("Ray Color",color) = (1,1,1,1)
}
SubShader
{
Tags { "RenderType"="Transparent" "Queue"="Transparent" }
LOD 100
//只需要透视渲染
Pass
{
Blend SrcAlpha OneMinusSrcAlpha
ZTest Greater ZWrite off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float4 normal : NORMAL;
};
struct v2f
{
float3 worldp2v : TEXCOORD0;
float3 worldn : TEXCOORD1;
float4 vertex : SV_POSITION;
};
float4 _RayColor;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.worldp2v = normalize(WorldSpaceViewDir(v.vertex));
o.worldn = normalize(UnityObjectToWorldNormal(v.normal.xyz));
return o;
}
fixed4 frag (v2f i) : SV_Target
{
//边缘强度衰减
float wei = saturate(dot(i.worldp2v,i.worldn));
fixed4 col = fixed4(_RayColor.rgb, 1 - wei);
return col;
}
ENDCG
}
}
}
只对透视部分进行渲染,效果如下:
差不多就得到遮挡透视渲染的效果了。