運動模糊
阿新 • • 發佈:2018-12-29
攝影常用的一招就是延時攝影,以使運動的物體產生運動模糊。
攝影技巧為:1,三角架固定相機;2,調長曝光時間;3,物件有運動物體和靜止物體參照
用了延時攝影,照片會產生藝術感,見下圖(2015年1月 拍攝於上海陸家嘴)
遊戲方面可喜的是Unity3d也可以實現類似效果,先看效果圖
第一張為無運動模糊
第二張為有運動模糊:主體人物清晰,場景運動
第三張為第二張gif中的一幀
第四張為有運動模糊:攝像機不動,人物動的效果(凌波微步)
原理:
累積緩衝區:允許在渲染到顏色緩衝區之後,不是把結果顯示到視窗上,而是把內容複製到累積緩衝區,這樣就可以把顏色緩衝區與累積緩衝區中的內容反覆進行混合,可以用來進行模糊處理和抗鋸齒。
我們程式碼的實現是利用了一塊累積快取來混合多張連續的影象。我們不斷的不當前影象疊加到之前渲染好的影象中。
shader程式碼
Shader "mgo/motion_blur" { Properties { _MainTex("Texture", 2D) = "white" {} _BlurSize("_BlurSize", range(0.001, 0.999)) = 0.9 } SubShader { Tags{ "RenderType" = "Opaque" } ZTest Off cull Off ZWrite Off Blend SrcAlpha OneMinusSrcAlpha Pass { Name "Main" CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex:POSITION; float2 uv:TEXCOORD0; }; struct v2f { float4 pos:SV_POSITION; float2 uv:TEXCOORD0; }; uniform sampler2D _MainTex; uniform half _BlurSize; v2f vert(appdata v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; } fixed4 frag(v2f i) : SV_Target { fixed4 color = tex2D(_MainTex,i.uv); //降低中心人物的運動模糊start float r = sqrt(pow(i.uv.x-0.5,2) + pow(i.uv.y-0.6,2)); float a = _BlurSize * pow((1 - r + 0.01), 5); if (a < 1 - _BlurSize) { a = 1 - _BlurSize; } color.a = a; //降低中心人物的運動模糊end //color.a = 1 - _BlurSize; return color; } ENDCG } } }
c#程式碼
using UnityEngine; namespace GameBase.Effect { public class MotionBlurEffect : ImageEffectBase { [SerializeField] [Range(0.001f, 0.999f)] private float _blurSize = 0.9f; private void OnEnable() { material.SetFloat("_BlurSize", _blurSize); } protected override void OnDisable() { base.OnDisable(); RenderTexture.ReleaseTemporary(_accumulationRT); _accumulationRT = null; } private RenderTexture _accumulationRT; void OnRenderImage(RenderTexture source, RenderTexture destination) { if(_accumulationRT == null || _accumulationRT.width != source.width || _accumulationRT.height != source.height) { if(_accumulationRT != null) RenderTexture.ReleaseTemporary(_accumulationRT); _accumulationRT = RenderTexture.GetTemporary(source.width, source.height, 0, source.format); _accumulationRT.hideFlags = HideFlags.HideAndDontSave; Graphics.Blit(source, _accumulationRT); } _accumulationRT.MarkRestoreExpected();//效能開銷很大,看下官方文件 Graphics.Blit(source, _accumulationRT, material); Graphics.Blit(_accumulationRT, destination); } } }