运动模糊效果实现详解
创作时间:
作者:
@小白创作中心
运动模糊效果实现详解
引用
CSDN
1.
https://blog.csdn.net/Go_Accepted/article/details/144316092
运动模糊效果,是一种用于模拟真实世界中快速移动物体产生的模糊现象的图像处理技术。当一个物体以较高速度移动时,由于人眼或摄像机的曝光时间过长,该物体会在图像中留下模糊的运动轨迹。这种效果在游戏、动画、电影中被广泛应用,以增加视觉真实性和动感。
基本原理
想要在屏幕后期处理中实现运动模糊,一般有两种常用方式:
- 累积缓存:物体快速移动时存储多帧图像信息,取它们之间的加权平均值作为最后的运动模糊图像。优点:质量高、效果好;缺点:计算量大,存储开销大
- 速度缓存:物体快速移动时存储多帧运动速度信息,利用速度来决定模糊的方向和大小。优点:性能较累积缓存好;缺点:效果较差,可能产生重影和伪影
基于累积缓存来实现动态模糊效果,但是不需要像累积缓存中那样存储多张场景信息,但是需要保存之前的渲染结果,不断把当前的渲染图像叠加到之前的渲染图像中,从而产生一种运动轨迹的视觉效果。相当于是基于累积缓存的优化,
性能会更好,但是模糊效果可能略有欠缺,但是效果也是可以接受的。
它的基本原理是:
用一个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);
}
}
热门推荐
如何分析企业的亏损原因及应对策略?这种分析对企业发展有什么启示?
“管”好体重,一起行动(健康中国 奋发有为)
南充首个综合性历史博物馆正式开馆,将为城市带来什么?
上市企业如何成功转型:战略规划与市场调整
广西南宁越南一日游攻略
工业互联网产业联盟发布《新型工业控制蓝皮书》
工业控制的救命稻草!PLC系统的备胎设计大揭秘
期货换手率的含义是什么?这种指标如何进行市场分析?
买电视机在网上买还是实体店买好?买电视怎么选择需要注意什么?
步伐调整:运动科学视角下的行走技巧
近视手术后用不用戴墨镜?
相对定位示例
相对定位示例
视觉盛宴:电商界的七种设计风格
血压高怎么调理才能恢复正常?这些方法你不妨试试
章程股东权利义务的定义及内容
过度医疗怎么界定?一文详解界定标准与维权途径
彩礼的智慧:以爱之名,共筑幸福基石
香菇的品种,常见以下9种
广州公积金可在佛山贷款买房,需满足条件
科研宝典·经验篇 | PowerPoint视觉表达技巧
PPT课件制作完整指南:从目标设定到分享发布
Web3与智能合约:揭秘区块链革命的双子星!
如何在饮水过程中避免给肾脏带来过大的负担?
儿科医生试用期转正工作总结
高血压与睡眠呼吸暂停的风险
网站关键词优化 提升搜索引擎排名的秘诀之道
护理人员排班的原则包括哪些?如何优化护理排班流程?
高校廉政风险评估与应对措施
“量化交易之王”西蒙斯离世,收益打败巴菲特