Dof景深基础

景深在后处理阶段完成:利用一张景深mask,将模糊处理的正常图片与原图做差值

景深mask制作:

1. 获取摄像机深度纹理,在unity中深度图挂载到实时光源上,如果使用烘焙灯则需要强制获取,添加代码:

private Camera currentCamera = null;
void Awake(){
    currentCamera = GetComponent<Camera>();
}

void OnEnable(){
    currentCamera.depthTextureMode |= DepthTextureMode.Depth;
}

void OnDisable(){
    currentCamera.depthTextureMode &= -DepthTextureMode.Depth;
}

2. 制作mask

_ProjectionParams.z:摄像机远裁面,由于在实际项目中景深效果一直跟随角色,不应该受到远裁面的影响,所以在获取深度信息时要乘以这个值。

定义景深值和焦距,焦距-景深 = 前焦,焦距+景深 = 远焦。当深度值小于前焦,景深用前焦-深度值,当深度值大于远焦,景深用深度值-远焦,加绝对值。

Pass{
    CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag                                                       // 顶点着色器和片源着色器声明

    #include "UnityCG.cginc"

    struct appdata{                                                             // 顶点着色器输入结构体,位置和UV
        float4 vertex : POSITION;
        float2 uv : TEXCOORD0;
    };

    struct v2f{                                                                 // 顶点着色器输出结构体,位置和UV
        float2 uv : TEXCOORD0;
        float4 vertex : SV_POSITION;
    };

    sampler2D _MainTex;
    sampler2D _BlurTex;                                                         // 模糊后的纹理
    sampler2D _CameraDepthTexture;                                              // 相机深度纹理
    float4 _BlurOffset;                                                         // 模糊范围偏移
    float _FocusDistance, _DepthOfField, _DofSmoothRange;                       // 焦点距离,景深,光滑过度  
    float _Step;               

    v2f vert (appdata v){
        v2f o;
        o.vertex = UnityObjectToClipPos(v.vertex);                              // 对象空间转换到裁剪空间
        o.uv = v.uv;
        return o;
    }       

    half4 frag (v2f i) : SV_Target{
        half4 col = tex2D(_MainTex, i.uv);                                      // 原图颜色
        half4 blur_col = tex2D(_BlurTex, i.uv);                                 // 模糊后的颜色
        
        
        // half depth = Linear01Depth(tex2D(_CameraDepthTexture, i.uv));        // 避免远裁面的值对景深效果的影响
        half depth = Linear01Depth(tex2D(_CameraDepthTexture, i.uv)).r * _ProjectionParams.z * _Step;//避免远裁面的值对景深效果的影响
        float focusNear = _FocusDistance - _DepthOfField;                       // 近焦距点
        float focusFar = _FocusDistance + _DepthOfField;                        // 远焦距点

        half final_depth = 0;
        if((depth>=focusNear)&&(depth<=focusFar));                              // 在景深范围内的点不做模糊
        else {
            if(depth<focusNear){                                                // 在景深范围之外的点,全部归到0-1
                final_depth = saturate(abs(focusNear-depth) * _DofSmoothRange); // 加入smooth使过度更平滑
            }else{
                final_depth = saturate(abs(focusFar-depth) * _DofSmoothRange);
                    
            }
        }

        half4 final_col = lerp(col, blur_col, final_depth*1.2);                 // 使用Mask进行混合
        //return half4(final_depth,final_depth,final_depth, 1);
        return half4(final_col.rgb, 1);
        //return half4(depth.xxx, 1);
        // return half4(col.rgb, 1);
        
    }                      

    ENDCG
}

3. 模糊图

Pass{
    CGPROGRAM

    #pragma vertex vert
    #pragma fragment frag                                                       // 顶点着色器和片源着色器声明

    #include "UnityCG.cginc"

    struct appdata{                                                             // 顶点着色器输入结构体,位置和UV
        float4 vertex : POSITION;
        float2 uv : TEXCOORD0;
    };

    struct v2f{                                                                 // 顶点着色器输出结构体,位置和UV
        float4 vertex : SV_POSITION;
        float2 uv : TEXCOORD0;
    };

    sampler2D _MainTex;
    float4 _BlurOffset;                                                         // 模糊偏移

    v2f vert (appdata v){
        v2f o;
        o.vertex = UnityObjectToClipPos(v.vertex);                              // 对象空间转换到裁剪空间
        o.uv = v.uv;
        return o;
    }       

    half4 frag (v2f i) : SV_Target{
                            
//----------------------------------- 高斯模糊处理 -------------------------------------//
        half2 uv1 = i.uv + _BlurOffset.xy * half2(1,0) * -2;
        half2 uv2 = i.uv + _BlurOffset.xy * half2(1,0) * -1;
        half2 uv3 = i.uv;
        half2 uv4 = i.uv + _BlurOffset.xy * half2(1,0) * 1;
        half2 uv5 = i.uv + _BlurOffset.xy * half2(1,0) * 2;

        half2 uv6 = i.uv + _BlurOffset.xy * half2(0,1) * -2;
        half2 uv7 = i.uv + _BlurOffset.xy * half2(0,1) * -1;
        half2 uv8 = i.uv;
        half2 uv9 = i.uv + _BlurOffset.xy * half2(0,1) * 1;
        half2 uv10 = i.uv + _BlurOffset.xy * half2(0,1) * 2;

        half4 s = 0;
        s += tex2D(_MainTex, uv1) * 0.05;
        s += tex2D(_MainTex, uv2) * 0.25;
        s += tex2D(_MainTex, uv3) * 0.40;
        s += tex2D(_MainTex, uv4) * 0.25;
        s += tex2D(_MainTex, uv5) * 0.05;

        s += tex2D(_MainTex, uv6) * 0.05;
        s += tex2D(_MainTex, uv7) * 0.25;
        s += tex2D(_MainTex, uv8) * 0.40;
        s += tex2D(_MainTex, uv9) * 0.25;
        s += tex2D(_MainTex, uv10) * 0.05;

        s /= 2;


        //return half4(final_depth.xxx, 1);
        return half4(s.rgb, 1);                                                 // 高斯模糊的效果对比
        //return half4(1,1,1, 1);                                                 // 高斯模糊的效果对比
    }                      

    ENDCG
}

教程地址:Dof景深

猜你喜欢

转载自blog.csdn.net/weixin_51327051/article/details/125851107
今日推荐