142 lines
4.2 KiB
Plaintext
142 lines
4.2 KiB
Plaintext
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
|
||
|
||
Shader "PostEffect/DepthOfField" {
|
||
|
||
Properties{
|
||
_MainTex("Base (RGB)", 2D) = "white" {}
|
||
_BlurTex("Blur", 2D) = "white"{}
|
||
}
|
||
|
||
CGINCLUDE
|
||
#include "UnityCG.cginc"
|
||
|
||
struct v2f_blur
|
||
{
|
||
float4 pos : SV_POSITION;
|
||
float2 uv : TEXCOORD0;
|
||
float4 uv01 : TEXCOORD1;
|
||
float4 uv23 : TEXCOORD2;
|
||
float4 uv45 : TEXCOORD3;
|
||
};
|
||
|
||
struct v2f_dof
|
||
{
|
||
float4 pos : SV_POSITION;
|
||
float2 uv : TEXCOORD0;
|
||
float2 uv1 : TEXCOORD1;
|
||
};
|
||
|
||
sampler2D _MainTex;
|
||
float4 _MainTex_TexelSize;
|
||
sampler2D _BlurTex;
|
||
sampler2D_float _CameraDepthTexture;
|
||
float4 _offsets;
|
||
float _focalDistance;
|
||
float _nearBlurScale;
|
||
float _farBlurScale;
|
||
|
||
//高斯模糊 vert shader(上一篇文章有详细注释)
|
||
v2f_blur vert_blur(appdata_img v)
|
||
{
|
||
v2f_blur o;
|
||
_offsets *= _MainTex_TexelSize.xyxy;
|
||
o.pos = UnityObjectToClipPos(v.vertex);
|
||
o.uv = v.texcoord.xy;
|
||
|
||
o.uv01 = v.texcoord.xyxy + _offsets.xyxy * float4(1, 1, -1, -1);
|
||
o.uv23 = v.texcoord.xyxy + _offsets.xyxy * float4(1, 1, -1, -1) * 2.0;
|
||
o.uv45 = v.texcoord.xyxy + _offsets.xyxy * float4(1, 1, -1, -1) * 3.0;
|
||
|
||
return o;
|
||
}
|
||
|
||
//高斯模糊 pixel shader(上一篇文章有详细注释)
|
||
fixed4 frag_blur(v2f_blur i) : SV_Target
|
||
{
|
||
fixed4 color = fixed4(0,0,0,0);
|
||
color += 0.40 * tex2D(_MainTex, i.uv);
|
||
color += 0.15 * tex2D(_MainTex, i.uv01.xy);
|
||
color += 0.15 * tex2D(_MainTex, i.uv01.zw);
|
||
color += 0.10 * tex2D(_MainTex, i.uv23.xy);
|
||
color += 0.10 * tex2D(_MainTex, i.uv23.zw);
|
||
color += 0.05 * tex2D(_MainTex, i.uv45.xy);
|
||
color += 0.05 * tex2D(_MainTex, i.uv45.zw);
|
||
return color;
|
||
}
|
||
|
||
//景深效果 vertex shader
|
||
v2f_dof vert_dof(appdata_img v)
|
||
{
|
||
v2f_dof o;
|
||
//mvp矩阵变换
|
||
o.pos = UnityObjectToClipPos(v.vertex);
|
||
//uv坐标传递
|
||
o.uv.xy = v.texcoord.xy;
|
||
o.uv1.xy = o.uv.xy;
|
||
//dx中纹理从左上角为初始坐标,需要反向
|
||
#if UNITY_UV_STARTS_AT_TOP
|
||
if (_MainTex_TexelSize.y < 0)
|
||
o.uv.y = 1 - o.uv.y;
|
||
#endif
|
||
return o;
|
||
}
|
||
|
||
fixed4 frag_dof(v2f_dof i) : SV_Target
|
||
{
|
||
//取原始清晰图片进行uv采样
|
||
fixed4 ori = tex2D(_MainTex, i.uv1);
|
||
//取模糊普片进行uv采样
|
||
fixed4 blur = tex2D(_BlurTex, i.uv);
|
||
//取当位置对应的深度值
|
||
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv);
|
||
//将深度值转化到01线性空间
|
||
depth = Linear01Depth(depth);
|
||
|
||
//如果depth小于焦点的物体,那么使用原始清晰图像,否则使用模糊的图像与清晰图像的差值,通过差值避免模糊和清晰之间明显的边界,结果为远景模糊效果
|
||
fixed4 final = (depth <= _focalDistance) ? ori : lerp(ori, blur, clamp((depth - _focalDistance) * _farBlurScale, 0, 1));
|
||
//上面的结果,再进行一次计算,如果depth大于焦点的物体,使用上面的结果和模糊图像差值,得到近景模糊效果
|
||
final = (depth > _focalDistance) ? final : lerp(ori, blur, clamp((_focalDistance - depth) * _nearBlurScale, 0, 1));
|
||
//焦点位置是清晰的图像,两边分别用当前像素深度距离焦点的距离进行差值,这样就达到原理焦点位置模糊的效果
|
||
|
||
//上面的?在编译时会被编译成if语句,GPU并不擅长分支计算,而且如果有分支,两个分支都要跑。这里给了一个更优化一些的计算方式,不过语法比较晦涩
|
||
/*float focalTest = clamp(sign(depth - _focalDistance),0,1);
|
||
fixed4 final = (1 - focalTest) * ori + focalTest * lerp(ori, blur, clamp((depth - _focalDistance) * _farBlurScale, 0, 1));
|
||
final = (focalTest)* final + (1 - focalTest) * lerp(ori, blur, clamp((_focalDistance - depth) * _nearBlurScale, 0, 1)); */
|
||
return final;
|
||
}
|
||
|
||
ENDCG
|
||
|
||
SubShader
|
||
{
|
||
//pass 0: 高斯模糊
|
||
Pass
|
||
{
|
||
ZTest Off
|
||
Cull Off
|
||
ZWrite Off
|
||
Fog{ Mode Off }
|
||
|
||
CGPROGRAM
|
||
#pragma vertex vert_blur
|
||
#pragma fragment frag_blur
|
||
ENDCG
|
||
}
|
||
|
||
//pass 1: 景深效果
|
||
Pass
|
||
{
|
||
|
||
ZTest Off
|
||
Cull Off
|
||
ZWrite Off
|
||
Fog{ Mode Off }
|
||
ColorMask RGBA
|
||
|
||
CGPROGRAM
|
||
#pragma vertex vert_dof
|
||
#pragma fragment frag_dof
|
||
ENDCG
|
||
}
|
||
}
|
||
} |