运动模糊效果

1、运动模糊效果

运动模糊效果,是一种用于 模拟真实世界中快速移动物体产生的模糊现象 的图像处理技术,当一个物体以较高速度移动时,由于人眼或摄像机的曝光时间过长,该物体会在图像中留下模糊的运动轨迹。这种效果游戏、动画、电影中被广泛应用,以增加视觉真实性和动感。

2、基本原理

想要在屏幕后期处理中实现运动模糊,一般有两种常用方式:

  1. 累积缓存:物体快速移动时存储多帧图像信息,取它们之间的加权平均值作为最后的运动模糊图像。优点:质量高、效果好;缺点:计算量大,存储开销大
  2. 速度缓存:物体快速移动时存储多帧运动速度信息,利用速度来决定模糊的方向和大小。优点:性能较累积缓存好;缺点:效果较差,可能产生重影和伪影

基于累积缓存来实现动态模糊效果,但是不需要像累积缓存中那样存储多张场景信息,但是需要保存之前的渲染结果,不断把当前的渲染图像叠加到之前的渲染图像中,从而产生一种运动轨迹的视觉效果。相当于是基于累积缓存的优化,
性能会更好,但是模糊效果可能略有欠缺,但是效果也是可以接受的。

它的基本原理是:
用一个RenderTexture记录上一次渲染的信息,然后每一次用新的屏幕图像信息和上一次的图像信息进行混合渲染,从而产生模糊效果(相当于用一张图保留了之前n次的叠加渲染结果)

在使用Graphics.Blit(源纹理,目标纹理,材质)方法时,如果目标纹理中包含内容,会直接认为目标纹理中的颜色为颜色缓冲区中的颜色,因此完全可以利用该方法,配合Shader代码将两张图片信息进行混合处理,从而实现运动模糊效果。
它的主要混合思路是:

  • RGB通道由两张图片根据模糊程度决定最终效果
  • A通道根据当前屏幕图像决定

利用一个模糊程度变量来控制运动模糊程度,值越大模糊程度越强;越小模糊程度越弱
利用两个Pass进行混合处理的方式:
第一个Pass:让当前屏幕图像 和 上一次的屏幕图像 进行指定RGB通道的颜色混合,目的是利用模糊程度参数控制两张图片的混合效果,值越大上一次屏幕内容保留的越多

第二个Pass:利用第一个Pass处理后得到的颜色在 和源纹理进行A通道的颜色混合,目的是保留源纹理透明度信息

混合方式如何设置

第一个Pass:

  • Blend SrcAlpha OneMinusSrcAlpha((源颜色 * SrcAlpha) + (目标颜色 * (1 - SrcAlpha)))
  • ColorMask RGB (只改变颜色缓冲区中的RGB通道)

第二个Pass:

  • Blend One Zero(最终颜色 = (源颜色 * 1) + (目标颜色 * 0))
  • ColorMask A(只改变颜色缓冲区中的A通道)
Shader "ShaderProj/12/MotionBlur"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        //模糊程度变量
        _BlurAmount("BlurAmount", Float) = 0.5
    }
    SubShader
    {
        CGINCLUDE

        #include "UnityCG.cginc"

        sampler2D _MainTex;
        fixed _BlurAmount;

        struct v2f
        {
            float2 uv : TEXCOORD0;
            float4 vertex : SV_POSITION;
        };

        v2f vert (appdata_base v)
        {
            v2f o;
            o.vertex = UnityObjectToClipPos(v.vertex);
            o.uv = v.texcoord;
            return o;
        }

        ENDCG

        ZTest Always
        Cull Off
        ZWrite Off

        Pass
        {
            Blend SrcAlpha OneMinusSrcAlpha
            ColorMask RGB

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment fragRGB

            fixed4 fragRGB (v2f i) : SV_Target
            {
                return fixed4(tex2D(_MainTex, i.uv).rgb, _BlurAmount);
            }
            ENDCG
        }

         Pass
        {
            Blend One Zero
            ColorMask A

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment fragA
            
            fixed4 fragA (v2f i) : SV_Target
            {
                return fixed4(tex2D(_MainTex, i.uv));
            }
            ENDCG
        }
    }
    Fallback Off
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MotionBlur : PostEffectBase
{
    [Range(0, 0.9f)]
    public float blurAmount = 0.5f;
    private RenderTexture accumulationTex;

    protected override void OnRenderImage(RenderTexture source, RenderTexture destination) {
        if (material != null) {
            //初始化堆积纹理 如果为空 或者 屏幕宽高变化了 都需要重新初始化
            if (accumulationTex == null ||
                accumulationTex.width != source.width ||
                accumulationTex.height != source.height) 
            {
                DestroyImmediate(accumulationTex);
                accumulationTex = new RenderTexture(source.width, source.height, 0);
                accumulationTex.hideFlags = HideFlags.HideAndDontSave;
                //保证第一次 累积纹理中也是有内容 因为之后 它的颜色 会作为颜色缓冲区中的颜色
                Graphics.Blit(source, accumulationTex);
            }
            
            material.SetFloat("_BlurAmount", 1.0f - blurAmount);

            //没有直接写入目标中的目的 也是可以通过accumulationTex记录当前渲染结果
            //那么在下一次时 它就相当于是上一次的结果了
            Graphics.Blit(source, accumulationTex, material);

            Graphics.Blit(accumulationTex, destination);
        }
        else
            Graphics.Blit(source, destination);
    }

    // 如果脚本失活 那么把累积纹理删除掉
    private void OnDisable() {
        DestroyImmediate(accumulationTex);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值