假运动模糊

基本思路
    用屏幕特效 多次绘制 每次都稍微放大一点
    放大的比例根据距屏幕中心点的距离增加

效果
    
 
比真的运动模糊更省资源,更可控

Shader "Other/FakeMotionBlur" {
	Properties {
		_MainTex ("Base (RGB)", 2D) = "white" {}
	}
	SubShader {
		CGINCLUDE
		
		#include "UnityCG.cginc"
		
		sampler2D _MainTex;  
		half4 _MainTex_TexelSize;

		half _SampleNum;
		half _Offset;
		half _DisScale;
		fixed _CenterX;
		fixed _CenterY;
		  
		struct v2f {
			float4 pos : SV_POSITION;
			half2 uv: TEXCOORD0;
		};
		  
		v2f vert(appdata_img v) {
			v2f o;

			o.pos = mul(UNITY_MATRIX_MVP, v.vertex);			
			o.uv = v.texcoord;
					 
			return o;
		}
		
		fixed4 frag(v2f i) : SV_Target {
			half dis = saturate(distance(fixed2(_CenterX, _CenterY), i.uv) * _DisScale);
			
			fixed3 sum = 0;
			for (int it = 0; it < _SampleNum; it++) {
				fixed2 dis2 = fixed2(_CenterX, _CenterY) - i.uv;
				fixed uvOffset = it * _Offset * dis;
				sum += tex2D(_MainTex, (i.uv + dis2 * uvOffset)).rgb / _SampleNum;
			}			
			
			return fixed4(sum, 1.0);
		}
		    
		ENDCG
		
		ZTest Always Cull Off ZWrite Off
		
		Pass {
			NAME "GAUSSIAN_BLUR_VERTICAL"
			
			CGPROGRAM
			  
			#pragma vertex vert  
			#pragma fragment frag
			  
			ENDCG  
		}
	} 
	FallBack "Diffuse"
}
C#
using UnityEngine;

[ExecuteInEditMode]
[RequireComponent(typeof(Camera))]
public class FakeMotionBlur : MonoBehaviour
{
	public Shader gaussianBlurShader;
	private Material gaussianBlurMaterial = null;

	public Material material {  
		get {
			gaussianBlurMaterial = CheckShaderAndCreateMaterial(gaussianBlurShader, gaussianBlurMaterial);
			return gaussianBlurMaterial;
		}
    }

    [Range(1, 50)]
    public int sampleNum = 10;

    [Range(0, 0.1f)]
    public float offset = 0.05f;

    [Range(0, 10)]
    public float disScale = 1.5f;

    [Range(0, 1)]
    public float centerX = 0.5f;
    [Range(0, 1)]
    public float centerY = 0.5f;


    /// 3rd edition: use iterations for larger blur
    void OnRenderImage(RenderTexture src, RenderTexture dest)
    {
        if (material != null)
        {
            int rtW = src.width;
            int rtH = src.height;

            material.SetFloat("_SampleNum", sampleNum);
            material.SetFloat("_Offset", offset);
            material.SetFloat("_DisScale", disScale);
            material.SetFloat("_CenterX", centerX);
            material.SetFloat("_CenterY", centerY);

            Graphics.Blit(src, dest, material, 0);
        }
        else
        {
            Graphics.Blit(src, dest);
        }
    }

    protected void Start()
    {
        if (gaussianBlurShader == null)
        {
            gaussianBlurShader = Shader.Find("Kingsoft/Other/FakeMotionBlur");
        }

        if (!CheckSupport())
        {
            enabled = false;
        }
    }

    // Called in CheckResources to check support on this platform
    protected bool CheckSupport()
    {
        if (SystemInfo.supportsImageEffects == false || SystemInfo.supportsRenderTextures == false)
        {
            Debug.LogWarning("This platform does not support image effects or render textures.");
            return false;
        }

        return true;
    }

    // Called when need to create the material used by this effect
    protected Material CheckShaderAndCreateMaterial(Shader shader, Material material)
    {
        if (shader == null)
        {
            return null;
        }

        if (shader.isSupported && material && material.shader == shader)
            return material;

        if (!shader.isSupported)
        {
            return null;
        }
        else
        {
            material = new Material(shader);
            material.hideFlags = HideFlags.DontSave;
            if (material)
                return material;
            else
                return null;
        }
    }
}
posted @ 2017-08-30 17:12  Hichy  阅读(252)  评论(0编辑  收藏  举报