【Unity】简单的深度虚化shader
实现效果
可以用于对地图场景边界的白模处理
实现方法
1.关键方法
UnityObjectToClipPos:将物体坐标转换为屏幕坐标
LinearEyeDepth:将屏幕坐标中的z值转换为实际的深度值
saturate:将值规范到0~1之间,小于0,则返回值为0,大于1,则返回值为1。
2.实现原理
通过LinearEyeDepth转换的深度值是的区间,只和相机的裁剪的远近截面有关。
这里将深度值除去远截面值(far)归一化的值赋给透明度,得到下图效果
float depth = LinearEyeDepth(i.depth);
float depth_normal =depth/47;
从图上看,虚化的值是从近截面一值到远截面,所以需要设置参数,控制虚化的范围和虚化的位置
用一个简单是数学公式
y
=
a
x
+
b
y=ax+b\\
y=ax+b
其中,
a
>
0
a>0
a>0;
0
<
y
<
1
0<y<1
0<y<1
a a a控制虚化的范围,也就是斜率
b b b控制虚化的位置
得到上图,发现近处的透明。再用1-值取反,完成效果。
3.完整shader
Shader "Custom/DepthShader" {
Properties
{
_MainTex("Texture", 2D) = "white" {}
_Color("Color",Color) = (1,1,1,1)
_Blur("Blur", Range(0, 40)) = 32
_Dis("Dis", Range(-40, 40)) = -32
}
SubShader
{
Tags { "Queue" = "Transparent" "RenderType" = "Opaque" }
LOD 100
Pass
{
Cull Back //剔除后面
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float depth : TEXCOORD1;
};
sampler2D _MainTex;
float _Blur;
float _Dis;
fixed4 _Color;
float4 _MainTex_ST;
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.depth = UnityObjectToClipPos(v.vertex).z;
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
float depth = LinearEyeDepth(i.depth);
float depth_normal =saturate((depth * _Blur)+ _Dis);
float4 col_Blur = depth_normal;
fixed4 col = tex2D(_MainTex, i.uv) * col_Blur * _Color;
return col;
}
ENDCG
}
}
}
4.Shader Graphs实现方法
ShaderGraphs深度虚化资源