作者:世卍界创意驿站肀 | 来源:互联网 | 2023-09-13 18:57
摄影常用的一招就是延时摄影,以使运动的物体产生运动模糊。
摄影技巧为:1,三角架固定相机;2,调长曝光时间;3,对象有运动物体和静止物体参照
用了延时摄影,照片会产生艺术感,见下图(2015年1月 拍摄于上海陆家嘴)
游戏方面可喜的是Unity3d也可以实现类似效果,先看效果图
第一张为无运动模糊
第二张为有运动模糊:主体人物清晰,场景运动
第三张为第二张gif中的一帧
第四张为有运动模糊:摄像机不动,人物动的效果(凌波微步)
原理:
累积缓冲区:允许在渲染到颜色缓冲区之后,不是把结果显示到窗口上,而是把内容复制到累积缓冲区,这样就可以把颜色缓冲区与累积缓冲区中的内容反复进行混合,可以用来进行模糊处理和抗锯齿。
我们代码的实现是利用了一块累积缓存来混合多张连续的图像。我们不断的不当前图像叠加到之前渲染好的图像中。
shader代码
Shader "mgo/motion_blur"
{Properties{_MainTex("Texture", 2D) &#61; "white" {}_BlurSize("_BlurSize", range(0.001, 0.999)) &#61; 0.9}SubShader{Tags{ "RenderType" &#61; "Opaque" }ZTest Offcull OffZWrite OffBlend SrcAlpha OneMinusSrcAlphaPass{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 &#61; UnityObjectToClipPos(v.vertex);o.uv &#61; v.uv;return o;}fixed4 frag(v2f i) : SV_Target{fixed4 color &#61; tex2D(_MainTex,i.uv);//降低中心人物的运动模糊startfloat r &#61; sqrt(pow(i.uv.x-0.5,2) &#43; pow(i.uv.y-0.6,2));float a &#61; _BlurSize * pow((1 - r &#43; 0.01), 5);if (a <1 - _BlurSize){a &#61; 1 - _BlurSize;}color.a &#61; a;//降低中心人物的运动模糊end//color.a &#61; 1 - _BlurSize;return color;}ENDCG}}
}
c#代码
using UnityEngine;namespace GameBase.Effect
{public class MotionBlurEffect : ImageEffectBase{[SerializeField][Range(0.001f, 0.999f)]private float _blurSize &#61; 0.9f;private void OnEnable(){material.SetFloat("_BlurSize", _blurSize);}protected override void OnDisable(){base.OnDisable();RenderTexture.ReleaseTemporary(_accumulationRT);_accumulationRT &#61; null;}private RenderTexture _accumulationRT;void OnRenderImage(RenderTexture source, RenderTexture destination){if(_accumulationRT &#61;&#61; null || _accumulationRT.width !&#61; source.width || _accumulationRT.height !&#61; source.height){if(_accumulationRT !&#61; null)RenderTexture.ReleaseTemporary(_accumulationRT);_accumulationRT &#61; RenderTexture.GetTemporary(source.width, source.height, 0, source.format);_accumulationRT.hideFlags &#61; HideFlags.HideAndDontSave;Graphics.Blit(source, _accumulationRT);}_accumulationRT.MarkRestoreExpected();//性能开销很大&#xff0c;看下官方文档Graphics.Blit(source, _accumulationRT, material);Graphics.Blit(_accumulationRT, destination);}}
}