Untiy使用Shader实现镜头模糊效果

Untiy使用Shader实现镜头模糊效果

前言

最近公司接了一个光学实验的项目,因为开发需求较模糊,我只能做一些简单的开发功能。于是在网上查相关资料,使用shader实现了一个简单的镜头模糊效果,在这里记录下,便于以后开发使用。

步骤

1.创建一个shader,用以实现镜头的模糊效果,实现代码如下所示:

Shader "CameraFilterPack/Blur_Movie" {
        Properties
        {
                _MainTex ("Base (RGB)", 2D) = "white" {}
                _TimeX ("Time", Range(0.0, 1.0)) = 1.0
                _Distortion ("_Distortion", Range(0.0, 1.0)) = 0.3
                _ScreenResolution ("_ScreenResolution", Vector) = (0.,0.,0.,0.)
                _Radius ("_Radius", Range(0.0, 1000.0)) = 700.0
                _Factor ("_Factor", Range(0.0, 1000.0)) = 200.0
        }
        SubShader
        {
                Pass
                {
                        ZTest Always
                        CGPROGRAM
                        #pragma vertex vert
                        #pragma fragment frag
                        #pragma fragmentoption ARB_precision_hint_fastest
                        #pragma target 3.0
                        #pragma glsl
                        #include "UnityCG.cginc"
                         
                         
                        uniform sampler2D _MainTex;
                        uniform float _TimeX;
                        uniform float _Distortion;
                        uniform float4 _ScreenResolution;
                        uniform float _Radius;
                        uniform float _Factor;
                         
                    struct appdata_t
            {
                float4 vertex   : POSITION;
                float4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
            };
  
            struct v2f
            {
                  half2 texcoord  : TEXCOORD0;
                  float4 vertex   : SV_POSITION;
                  fixed4 color    : COLOR;
           };  
              
                          v2f vert(appdata_t IN)
            {
                v2f OUT;
                OUT.vertex = UnityObjectToClipPos(IN.vertex);
                OUT.texcoord = IN.texcoord;
                OUT.color = IN.color;
                 
                return OUT;
            }
                      #define tex2D(sampler,uvs)  tex2Dlod( sampler , float4( ( uvs ) , 0.0f , 0.0f) )
                        float4 frag (v2f i) : COLOR
                        {
                                float factor = _Factor/_ScreenResolution.y * 64.0;
                                float radius = _Radius/_ScreenResolution.x * 2.0;
                                float4 col = 0.0;
                                float4 accumColx = 0.0;
                                float4 accumW = 0.0;
                                for (float j = -5.0; j < 5.0; j += 1.0)
                                {
                                        for (float u = -5.0; u < 5.0; u += 1.0)
                                        {
                                                float2 offsetx = (1.0/_ScreenResolution.xy) * float2(u + j, j - u);
                                                col = tex2D(_MainTex, i.texcoord.xy + offsetx * radius);
                                                float4 movie = 1.0 + col * col * col * factor;
                                                accumColx = accumColx + col * movie;
                                                accumW += movie;
                                        }
                                } 
                                accumColx = accumColx/accumW;
                                return accumColx;
                        }
                         
                        ENDCG
                }
                 
        }
}

2.创建CameraFilterPack_Blur_Movie.cs脚本,用以调用实现镜头模糊功能的调用,代码如下所示:

using UnityEngine;
[ExecuteInEditMode]
[AddComponentMenu("Camera Filter Pack/Blur/Movie")]
public class CameraFilterPack_Blur_Movie : MonoBehaviour
{
    #region Variables
    public Shader SCShader;
    private float TimeX = 1.0f;
    private Vector4 ScreenResolution;
    private Material SCMaterial;
    [Range(0, 1000)]
    public float Radius = 150.0f;
    [Range(0, 1000)]
    public float Factor = 200.0f;
    [Range(1, 8)]
    public int FastFilter = 2;

    //public static float ChangeRadius;
    public float ChangeRadius;
    //public static float ChangeFactor;
    public float ChangeFactor;
    //public static int ChangeFastFilter;
    public int ChangeFastFilter;

    #endregion

    #region Properties
    Material material
    {
        get
        {
            if (SCMaterial == null)
            {
                SCMaterial = new Material(SCShader);
                SCMaterial.hideFlags = HideFlags.HideAndDontSave;
            }
            return SCMaterial;
        }
    }
    #endregion
    void Start()
    {
        ChangeRadius = Radius;
        ChangeFactor = Factor;
        ChangeFastFilter = FastFilter;
        SCShader = Shader.Find("CameraFilterPack/Blur_Movie");

        if (!SystemInfo.supportsImageEffects)
        {
            enabled = false;
            return;
        }
    }

    void OnRenderImage(RenderTexture sourceTexture, RenderTexture destTexture)
    {

        if (SCShader != null)
        {
            int DownScale = FastFilter;
            TimeX += Time.deltaTime;
            if (TimeX > 100) TimeX = 0;
            material.SetFloat("_TimeX", TimeX);
            material.SetFloat("_Radius", Radius / DownScale);
            material.SetFloat("_Factor", Factor);
            material.SetVector("_ScreenResolution", new Vector2(Screen.width / DownScale, Screen.height / DownScale));
            int rtW = sourceTexture.width / DownScale;
            int rtH = sourceTexture.height / DownScale;

            if (FastFilter > 1)
            {
                RenderTexture buffer = RenderTexture.GetTemporary(rtW, rtH, 0);
                Graphics.Blit(sourceTexture, buffer, material);
                Graphics.Blit(buffer, destTexture);
                RenderTexture.ReleaseTemporary(buffer);
            }
            else
            {
                Graphics.Blit(sourceTexture, destTexture, material);
            }
        }
        else
        {
            Graphics.Blit(sourceTexture, destTexture);
        }


    }
    void OnValidate()
    {
        ChangeRadius = Radius;
        ChangeFactor = Factor;
        ChangeFastFilter = FastFilter;
    }
    // Update is called once per frame
    void Update()
    {
        if (Application.isPlaying)
        {
            Radius = ChangeRadius;
            Factor = ChangeFactor;
            FastFilter = ChangeFastFilter;
        }
#if UNITY_EDITOR
        if (Application.isPlaying != true)
        {
            SCShader = Shader.Find("CameraFilterPack/Blur_Movie");

        }
#endif

    }

    void OnDisable()
    {
        if (SCMaterial)
        {
            DestroyImmediate(SCMaterial);
        }

    }

}

3.将上述脚本挂载到场景中的Camera中,并将shader文件拖拽到脚本上,如下图所示:
在这里插入图片描述
4.修改脚本中的Radius的值,即实现了镜头模糊效果,如下图所示:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

波波斯维奇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值