UnityShader实例16:屏幕特效之径向模糊(Radial Blur)

2024-05-28 23:32

本文主要是介绍UnityShader实例16:屏幕特效之径向模糊(Radial Blur),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

径向模糊(Radial Blur)


概述


       径向模糊,是一种从中心向外呈幅射状的逐渐模糊的效果(如下图),在图形处理软件photoshop里面也有这个模糊滤镜。而在游戏中常常用来模拟一些动感的效果,如鬼泣4中的场景切换特效,和一些技能打击特效;赛车游戏也尝用来模拟动感模糊,如狂野飙车,极品飞车等。本例将实现一个类似效果适用于手机平台的径向模糊效果,将开放模糊强度以及模糊范围两个参数调整模糊效果。





实现原理及流程


       径向模糊和高斯模糊等其他模糊效果一样,原像素都要周围附近的像素的颜色值共同影响。如高斯模糊就是将原像素四周像素的颜色加权求和作为原像素的颜色以达到模糊的目的,而径向模糊的特点是从某个像素为中心向外辐射状扩散,因此需要采样的像素在原像素和中间点像素的连线上,不同连线上的点不会相互影响。简单的说,就是像素的颜色是由该像素的点与中心点之间连线上进行采样(如图),然后求将这些采样点颜色的加权平均和作为该像素的颜色。根据径向模糊的特性,离目标点越近采样点越密集,反之亦然。

       由此我们可以大概确定下径向模糊实现的流程:
  •        第一步:确定径向模糊的中心点,通常取图像的正中心点、
  •        第二步:计算采样像素与中心点的距离,根据距离确定偏移程度,即离中心点越远,偏移量越大。
  •        第三步:将采样点的颜色值做加权求和,本例使用平均求和。
  •        第四步:将前面的结果与原图像做一个lerp差值合成


基于移动平台的优化


       从径向模糊的原理可知,由于需要获知每个像素点距离中心点的距离,并且根据采样点的距离采样偏移不一样,,因此不能像高斯模糊那样在vert函数里面进行uv整理偏移采样,只能在frag函数中逐像素计算,因此当分辨率越大,计算量成几何倍数增长。对于一些高分辨率的设备,比如ipad4,iphone6等,如果直接采样的话,则可能导致帧率下降得很厉害的结果,甚至还不如iphone5的帧率 。
       没法从vert函数那里优化,那么只能降低frag函数部分的采样,最简单的方法就是降低屏幕图像的分辨率。但付出的代价就是需要两个缓存来存贮屏幕图像,增加2个drawcall,不过还是值得的,真机测试帧率提高了不少。流程也因此也得改一下,得分两个pass分别处理模糊计算(降低分辨率计算)和lerp差值合成(恢复到正常分辨率)。这样保证最后输出的结果还是原来的分辨率,清晰部分不变,而模糊部分质量稍微有下降,但实际效果还是可以接受的。



shader实现


       这里我只放出关键代码,需要完整代码可以点文章后面链接下载。 
       根据需求我们需要从C#脚本传递两个参数_SampleDist和_SampleStrength分别控制模糊强度和模糊范围:
		uniform float _SampleDist;uniform float _SampleStrength;

       从优化流程可知,我们需要两个pass分别处理模糊计算和lerp差值合成,先处理模糊计算,主要计算在frag函数中完成。需要注意的是,从C#传递过来的图像是已经降低过分辨率的,关键代码如下:
		fixed4 fragRadialBlur (v2f i) : COLOR{//计算辐射中心点位置fixed2 dir = 0.5-i.texcoord;//计算取样像素点到中心点距离fixed dist = length(dir);dir /= dist;dir *= _SampleDist;fixed4 sum = tex2D(_MainTex, i.texcoord - dir*0.01);sum += tex2D(_MainTex, i.texcoord - dir*0.02);sum += tex2D(_MainTex, i.texcoord - dir*0.03);sum += tex2D(_MainTex, i.texcoord - dir*0.05);sum += tex2D(_MainTex, i.texcoord - dir*0.08);sum += tex2D(_MainTex, i.texcoord + dir*0.01);sum += tex2D(_MainTex, i.texcoord + dir*0.02);sum += tex2D(_MainTex, i.texcoord + dir*0.03);sum += tex2D(_MainTex, i.texcoord + dir*0.05);sum += tex2D(_MainTex, i.texcoord + dir*0.08);sum *= 0.1;return sum;}



       另外一个pass用上一个pass处理好的模糊结果与源图像做差值合成,其中_SampleStrength控制模糊的范围,这一步使用的是正常分辨率的计算。

		fixed4 fragCombine (v2f i) : COLOR{fixed dist = length(0.5-i.texcoord);fixed4  col = tex2D(_MainTex, i.texcoord);fixed4  blur = tex2D(_BlurTex, i.texcoord);col=lerp(col, blur,saturate(_SampleStrength*dist));return col;}



C#脚本

       C#脚本比较简单,主要是将屏幕图像降低分辨率传给shader处理,这里只放出关键代码,需要完整代码请到文章后面的下载链接下载。

	void OnRenderImage (RenderTexture sourceTexture, RenderTexture destTexture){	#if UNITY_EDITORFindShaders ();CheckSupport ();CreateMaterials ();	#endifif(SampleDist != 0 && SampleStrength != 0){int rtW = sourceTexture.width/8;int rtH = sourceTexture.height/8;RadialBlurMaterial.SetFloat ("_SampleDist", SampleDist);RadialBlurMaterial.SetFloat ("_SampleStrength", SampleStrength);	RenderTexture rtTempA = RenderTexture.GetTemporary (rtW, rtH, 0,RenderTextureFormat.Default);rtTempA.filterMode = FilterMode.Bilinear;Graphics.Blit (sourceTexture, rtTempA);RenderTexture rtTempB = RenderTexture.GetTemporary (rtW, rtH, 0,RenderTextureFormat.Default);rtTempB.filterMode = FilterMode.Bilinear;Graphics.Blit (rtTempA, rtTempB, RadialBlurMaterial,0);RadialBlurMaterial.SetTexture ("_BlurTex", rtTempB);Graphics.Blit (sourceTexture, destTexture, RadialBlurMaterial,1);RenderTexture.ReleaseTemporary(rtTempA);RenderTexture.ReleaseTemporary(rtTempB);}else{Graphics.Blit(sourceTexture, destTexture);}


本例实现效果如图




总结

       本例径向模糊特效是为移动平台服务的,主要的优化也是有C#脚本来实现,在这里我们将屏幕图像长宽分别缩小为原来的8分之一,那么计算量至少减少为原来64分之一。以每个点需要10次采样计算的话,节省的计算量是惊人的。在实际应用中,我们可以根据机型或者分辨率,来控制分辨率缩小的比率,在美术效果和计算效率取到一个比较合理的平衡,而不是本例的一刀切,不管分辨率大小一律除以8,可能导致一些分辨率比较低的机型效果缩水严重。



下载链接

       屏幕特效之径向模糊

这篇关于UnityShader实例16:屏幕特效之径向模糊(Radial Blur)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1012004

相关文章

swiper实例

大家好,我是燐子,今天给大家带来swiper实例   微信小程序中的 swiper 组件是一种用于创建滑动视图的容器组件,常用于实现图片轮播、广告展示等效果。它通过一系列的子组件 swiper-item 来定义滑动视图的每一个页面。 基本用法   以下是一个简单的 swiper 示例代码:   WXML(页面结构) <swiper autoplay="true" interval="3

Java面试题:通过实例说明内连接、左外连接和右外连接的区别

在 SQL 中,连接(JOIN)用于在多个表之间组合行。最常用的连接类型是内连接(INNER JOIN)、左外连接(LEFT OUTER JOIN)和右外连接(RIGHT OUTER JOIN)。它们的主要区别在于它们如何处理表之间的匹配和不匹配行。下面是每种连接的详细说明和示例。 表示例 假设有两个表:Customers 和 Orders。 Customers CustomerIDCus

笔记本电脑屏幕模糊?6招恢复屏幕清晰!

在数字化时代的浪潮中,笔记本电脑已成为我们生活、学习和工作中不可或缺的一部分。然而,当那曾经清晰明亮的屏幕逐渐变得模糊不清时,无疑给我们的使用体验蒙上了一层阴影。屏幕模糊不仅影响视觉舒适度,更可能对我们的工作效率和眼睛健康构成威胁。 遇到笔记本电脑屏幕模糊的情况时我们应该如何解决?本文将与大家分享6个简单易懂的解决方法。 方法一:调整Windows分辨率 电脑屏幕模糊显示不清晰怎

16.Spring前世今生与Spring编程思想

1.1.课程目标 1、通过对本章内容的学习,可以掌握Spring的基本架构及各子模块之间的依赖关系。 2、 了解Spring的发展历史,启发思维。 3、 对 Spring形成一个整体的认识,为之后的深入学习做铺垫。 4、 通过对本章内容的学习,可以了解Spring版本升级的规律,从而应用到自己的系统升级版本命名。 5、Spring编程思想总结。 1.2.内容定位 Spring使用经验

如何实现一台机器上运行多个MySQL实例?

在一台机器上一个MySQL服务器运行多个MySQL实例有什么好处?这里我先入为主给大家介绍这样做至少存在两个好处(看完这篇文章后理解会更透彻): (1)减轻服务器链接负担 (2)为不同的用户提供不同的mysqld服务器的访问权限以方便这些用户进行自我管理。   下面我介绍具体的实现过程: 一、准备工作     台式机一台、Windows系统、MySQL服务器(我安装的版本是MySQL

【Qt6.3 基础教程 16】 掌握Qt中的时间和日期:QTimer和QDateTime的高效应用

文章目录 前言QTimer:定时任务的强大工具QTimer的基本用法高级特性:单次定时器 QDateTime:处理日期和时间获取当前日期和时间日期和时间的格式化输出日期和时间计算 用例:创建一个倒计时应用结论 前言 在开发桌面应用程序时,处理时间和日期是一个常见且重要的任务。Qt框架提供了强大的工具来处理与时间相关的功能,其中QTimer和QDateTime是最核心的类。本

Docker Compose--安装Nginx--方法/实例

原文网址:Docker Compose--安装Nginx--方法/实例_IT利刃出鞘的博客-CSDN博客 简介 说明 本文介绍Docker Compose如何安装Nginx。 目录结构 ├── config│   ├── cert│   │   ├── xxx_bundle.pem│   │   └── xxx.key│   ├── conf.d│   └── nginx.co

Linux float int和16进制互相转换

Linux 上float int和16进制互换操作。之前把float转16进制,也就是转成4个字节,方便使用串口传输嘛。使用的方法是: //float 转 16进制float x_pid_p = 15.0;unsigned char * bValue = (unsigned char *)& x_pid_p;printf("%x\t%x\t%x\t%x\n", bValue[0], bVa

2021-02-16物料档案条码添加和蓝牙条码标签打印,金蝶安卓盘点机PDA,金蝶仓库条码管理WMS系统

物料档案条码添加和蓝牙条码标签打印,金蝶安卓盘点机PDA https://member.bilibili.com/platform/upload-manager/article 本期视频我们来讲解一下汉点机PDA条码添加和条码标签蓝牙便携打印: 在实际使用中,我们商品有两种情况: 一种是商品本身就有条码, 比如:超市卖的可口可乐,牛奶等商品,商品本身就有69开头的国标码,那么我们就可以使用盘点

用 idea 启动多个实例

在学习负载均衡的时候,要模拟多个实例均提供一个服务,我们要如何用 idea 启动多个实例呢?         如下图,我们已经启动了一个 ProductService 服务,现在想再启动两个相同的服务 1. 选中要启动的服务,右键选择 Copy Configuration... 2 在弹出的框中,选择 Modify options -> Add VM option