什么是运动模糊 在摄像机曝光的时候,拍摄场景发生变换,就会产生模糊的画面。运动模糊可以让物体运动看起来更加真实平滑。
实现方法1:利用一块累计缓存accumulation buffer,用来混合多张连续的图像,当物体快速移动,我们取多张图像的平均值作为最后的图像。
缺点:性能消耗大,需要在同一帧渲染多次场景。
实现方法2:使用速度缓存velocity buffer,这个缓存存储像素当前的运动速度,利用该值决定模糊的方向。
方法1实现 不需要渲染多次场景,只需要保存之前的渲染结果,不断把当前的渲染图像叠加之前的渲染图像,产生一种运动轨迹的视角效果。可以提高性能,但是模糊效果肯定不如之前的效果。
脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 using UnityEngine;using System.Collections;public class MotionBlur : PostEffectsBase { public Shader motionBlurShader; private Material motionBlurMaterial = null ; public Material material { get { motionBlurMaterial = CheckShaderAndCreateMaterial(motionBlurShader, motionBlurMaterial); return motionBlurMaterial; } } [Range(0.0f, 0.9f) ] public float blurAmount = 0.5f ; private RenderTexture accumulationTexture; void OnDisable () { DestroyImmediate(accumulationTexture); } void OnRenderImage (RenderTexture src, RenderTexture dest ) { if (material != null ) { if (accumulationTexture == null || accumulationTexture.width != src.width || accumulationTexture.height != src.height) { DestroyImmediate(accumulationTexture); accumulationTexture = new RenderTexture(src.width, src.height, 0 ); accumulationTexture.hideFlags = HideFlags.HideAndDontSave; Graphics.Blit(src, accumulationTexture); } accumulationTexture.MarkRestoreExpected(); material.SetFloat("_BlurAmount" , 1.0f - blurAmount); Graphics.Blit (src, accumulationTexture, material); Graphics.Blit (accumulationTexture, dest); } else { Graphics.Blit(src, dest); } } }
shader 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 Shader "Unity Shaders Book/Chapter 12/Motion Blur" { Properties { _MainTex ("Base (RGB)" , 2 D) = "white" {} _BlurAmount ("Blur Amount" , Float) = 1.0 } SubShader { CGINCLUDE #include "UnityCG.cginc" sampler2D _MainTex; fixed _BlurAmount; struct v2f { float4 pos : SV_POSITION; half2 uv : TEXCOORD0; }; v2f vert (appdata_img v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.uv = v.texcoord; return o; } fixed4 fragRGB (v2f i) : SV_Target { return fixed4(tex2D(_MainTex, i.uv).rgb, _BlurAmount); } half4 fragA (v2f i) : SV_Target { return tex2D(_MainTex, i.uv); } ENDCG ZTest Always Cull Off ZWrite Off Pass { Blend SrcAlpha OneMinusSrcAlpha ColorMask RGB CGPROGRAM #pragma vertex vert #pragma fragment fragRGB ENDCG } Pass { Blend One Zero ColorMask A CGPROGRAM #pragma vertex vert #pragma fragment fragA ENDCG } } FallBack Off }