unity shader景深效果

实现效果

景深效果

实现思路

由两张图组成,分别是远处的模糊状态和近处的清晰状态,根据物体的深度判断物体离摄像机的距离确定物体的状态。两个图进行插值,越近越靠近清晰的图像。

代码

脚本代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DepthOfField : PostEffectsBase
{
    public Shader bloomShader;
    private Material bloomMaterial = null;
    public Material material
    {
        get
        {
            bloomMaterial = CheckShaderAndCreateMaterial(bloomShader, bloomMaterial);
            return bloomMaterial;
        }
    }

    //迭代次数
    [Range(0, 4)]
    public int iterations = 3;
    //模糊范围
    [Range(0.2f, 3.0f)]
    public float blurSpread = 0.6f;
    //缩放系数
    [Range(1, 8)]
    public int downSample = 2;
    [Range(0.0f, 50f)]
    //近处与远处的分割线的距离
    public float Threshold = 10f;
    [Range(0.0f, 1.0f)]
    //近处的模糊系数
    public float NearBlurSize = 0.0f;
    //远处的模糊系数
    [Range(0.0f, 1.0f)]
    public float FarBlurSize = 1.0f;
    private Camera myCamera;
    public Camera camera
    {
        get
        {
            if (myCamera == null)
            {
                myCamera = GetComponent<Camera>();
            }
            return myCamera;
        }
    }
    private Transform myCameraTransform;
    public Transform cameraTransform
    {
        get
        {
            if (myCameraTransform == null)
            {
                myCameraTransform = camera.transform;
            }
            return myCameraTransform;
        }
    }
    // Start is called before the first frame update
    private void OnEnable()
    {
        camera.depthTextureMode |= DepthTextureMode.Depth;
    }
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }
    public void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        if (material != null)
        {
            //传参
            material.SetFloat("_Threshold", Threshold);
            material.SetFloat("_NearBlurSize", NearBlurSize);
            material.SetFloat("_FarBlurSize", FarBlurSize);
            int rtW = source.width / downSample;
            int rtH = source.height / downSample;

            RenderTexture buffer0 = RenderTexture.GetTemporary(rtW, rtH, 0);
            buffer0.filterMode = FilterMode.Bilinear;
            //传递清晰的图像
            buffer0 = source;
            for (int i = 0; i < 3; i++)
            {
                material.SetFloat("_BlurSize", 1.0f + i * blurSpread);

                RenderTexture buffer1 = RenderTexture.GetTemporary(rtW, rtH, 0);
                Graphics.Blit(buffer0, buffer1, material, 0);
                RenderTexture.ReleaseTemporary(buffer0);
                buffer0 = buffer1;
                buffer1 = RenderTexture.GetTemporary(rtW, rtH, 1);
                Graphics.Blit(buffer0, buffer1, material, 1);
                RenderTexture.ReleaseTemporary(buffer0);
                buffer0 = buffer1;
            }

            //将提取出来的图像模糊处理后存储到纹理中
            material.SetTexture("_Blur", buffer0);
            //利用第四个pass将模糊的图像和原图合并起来
            Graphics.Blit(source, destination, material,2);
            RenderTexture.ReleaseTemporary(buffer0);
        }
        else
        {
            Graphics.Blit(source, destination);
        }
    }
}

shader

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Custom/depthoffield"
{
 Properties
    {
        _MainTex ("Base (RGB)", 2D) = "white" {}
    }
    SubShader
    {
    CGINCLUDE

    #include "unityCG.cginc"
    sampler2D _MainTex;
    half4 _MainTex_TexelSize;
    sampler2D _Blur;
    float _Threshold;
    sampler2D _CameraDepthTexture;
    float _NearBlurSize;
    float _FarBlurSize;

    //混合图像的片段着色器的结构图
    struct v2fblur{
    float4 pos:SV_POSITION;
    //清晰和模糊的纹理坐标一致
    half2 uv:TEXCOORD0;
    //深度纹理坐标
    half2 uv_depth:TEXCOORD1;
    };

    //顶点着色器
    v2fblur vertBlur(appdata_img v){
    v2fblur o;
    o.pos =UnityObjectToClipPos(v.vertex);
    o.uv =v.texcoord;
    o.uv_depth =v.texcoord;
    //平台差异化处理
    #if UNITY_UV_STARTS_AT_TOP
    if(_MainTex_TexelSize.y<0.0){
    o.uv.y=1.0-o.uv.y;
    }
    #endif

    return o;
    }

    //片段着色器
    fixed4 fragBlur(v2fblur i):SV_Target{
    //清晰图像
    fixed4 maincolor = tex2D(_MainTex,i.uv);
    //模糊图像
    fixed4 blurcolor =tex2D(_Blur,i.uv);
    //深度值
    float linearDepth =LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv_depth));
    //与临界值的插值
    float dis = (linearDepth-_Threshold);
    if(dis<=0){
    dis*=_NearBlurSize;
    }else{
    dis*=_FarBlurSize;
    }
    //限定在[0,1]
    dis = clamp(abs(dis),0,1);
    //插值颜色,近处的模糊系数小,远处大
    return lerp(maincolor,blurcolor,dis);
    }
    ENDCG

    Tags{"RenderType"="Opaque"}
    ZTest Always Cull Off ZWrite Off

    //模糊处理
    UsePass "Custom/Chapter12-GaussianBlur/GAUSSIAN_BLUR_VERTICAL"
    UsePass "Custom/Chapter12-GaussianBlur/GAUSSIAN_BLUR_HORIZONTAL"

    //混合图像pass
    Pass{
    CGPROGRAM
    #pragma vertex vertBlur
    #pragma fragment fragBlur
    ENDCG
    }
    }
    FallBack "Diffuse"
}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值