在Unity中,Shader是创建高质量视觉效果的关键。景深(Depth of Field,简称DOF)是模拟真实摄影中的一种视觉效果,通过模糊前景和背景来强调主体,使得画面更具层次感和真实感。本文将带你探索Unity Shader中的景深设置,让你轻松打造逼真的视觉效果。
景深原理
在真实世界中,人的眼睛具有自动调节焦距的能力,从而能够在不同距离的物体上获得清晰的成像。景深则是描述了眼睛可以清晰成像的距离范围。在Unity中,我们通过模拟这一原理,为场景中的物体设置不同的清晰度和模糊度,从而实现景深效果。
景深Shader实现
Unity提供了多种实现景深效果的方法,以下将介绍几种常见的景深Shader技术:
1. 简单景深Shader
这种Shader实现方法简单,通过计算物体与摄像机的距离,对超出景深范围的物体进行模糊处理。
Shader "Custom/SimpleDepthOfField"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_FocusDistance ("Focus Distance", Float) = 5.0
_FocalLength ("Focal Length", Float) = 50.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
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 distance : TEXCOORD1;
};
sampler2D _MainTex;
float _FocusDistance;
float _FocalLength;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.distance = length(v.vertex.z * _FocalLength / v.vertex.w - _FocusDistance);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
if (i.distance < 0.1)
{
col.rgb *= 1.2; // 超出景深范围,增加颜色饱和度
}
return col;
}
ENDCG
}
}
}
2. 双线性景深Shader
双线性景深Shader在简单景深Shader的基础上,通过插值处理,使得模糊效果更加平滑。
Shader "Custom/BilinearDepthOfField"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_FocusDistance ("Focus Distance", Float) = 5.0
_FocalLength ("Focal Length", Float) = 50.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
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;
float2 screenUV : TEXCOORD1;
float distance : TEXCOORD2;
};
sampler2D _MainTex;
float _FocusDistance;
float _FocalLength;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.screenUV = UnityObjectToScreen(v.vertex);
o.distance = length(v.vertex.z * _FocalLength / v.vertex.w - _FocusDistance);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
float2 uv = lerp(i.uv, i.screenUV, saturate((i.distance - 0.1) * 10.0));
fixed4 col = tex2D(_MainTex, uv);
if (i.distance < 0.1)
{
col.rgb *= 1.2; // 超出景深范围,增加颜色饱和度
}
return col;
}
ENDCG
}
}
}
3. 基于深度纹理的景深Shader
基于深度纹理的景深Shader可以更真实地模拟景深效果,同时支持硬件加速。
Shader "Custom/DepthBasedDepthOfField"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_DepthTex ("Depth Texture", 2D) = "white" {}
_FocusDistance ("Focus Distance", Float) = 5.0
_FocalLength ("Focal Length", Float) = 50.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
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;
sampler2D _DepthTex;
float _FocusDistance;
float _FocalLength;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.depth = tex2D(_DepthTex, o.uv).r;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
float depth = i.depth;
float2 uv = i.uv;
float4 col = tex2D(_MainTex, uv);
float distance = length(i.vertex.z * _FocalLength / i.vertex.w - _FocusDistance);
if (distance < 0.1)
{
col.rgb *= 1.2; // 超出景深范围,增加颜色饱和度
}
return col;
}
ENDCG
}
}
}
总结
通过本文的介绍,相信你已经掌握了Unity Shader中景深设置的技巧。在实际项目中,你可以根据自己的需求选择合适的景深Shader,并调整相关参数,从而打造出逼真的视觉效果。希望这些知识能帮助你创作出更多精彩的作品!
