基本思路
用屏幕特效 多次绘制 每次都稍微放大一点
放大的比例根据距屏幕中心点的距离增加
效果
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;
}
}
}