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

相关文章

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

C++操作符重载实例(独立函数)

C++操作符重载实例,我们把坐标值CVector的加法进行重载,计算c3=c1+c2时,也就是计算x3=x1+x2,y3=y1+y2,今天我们以独立函数的方式重载操作符+(加号),以下是C++代码: c1802.cpp源代码: D:\YcjWork\CppTour>vim c1802.cpp #include <iostream>using namespace std;/*** 以独立函数

实例:如何统计当前主机的连接状态和连接数

统计当前主机的连接状态和连接数 在 Linux 中,可使用 ss 命令来查看主机的网络连接状态。以下是统计当前主机连接状态和连接主机数量的具体操作。 1. 统计当前主机的连接状态 使用 ss 命令结合 grep、cut、sort 和 uniq 命令来统计当前主机的 TCP 连接状态。 ss -nta | grep -v '^State' | cut -d " " -f 1 | sort |

Java Websocket实例【服务端与客户端实现全双工通讯】

Java Websocket实例【服务端与客户端实现全双工通讯】 现很多网站为了实现即时通讯,所用的技术都是轮询(polling)。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发 出HTTP request,然后由服务器返回最新的数据给客服端的浏览器。这种传统的HTTP request 的模式带来很明显的缺点 – 浏 览器需要不断的向服务器发出请求,然而HTTP

【JavaScript】LeetCode:16-20

文章目录 16 无重复字符的最长字串17 找到字符串中所有字母异位词18 和为K的子数组19 滑动窗口最大值20 最小覆盖字串 16 无重复字符的最长字串 滑动窗口 + 哈希表这里用哈希集合Set()实现。左指针i,右指针j,从头遍历数组,若j指针指向的元素不在set中,则加入该元素,否则更新结果res,删除集合中i指针指向的元素,进入下一轮循环。 /*** @param

828华为云征文|华为云Flexus X实例docker部署rancher并构建k8s集群

828华为云征文|华为云Flexus X实例docker部署rancher并构建k8s集群 华为云最近正在举办828 B2B企业节,Flexus X实例的促销力度非常大,特别适合那些对算力性能有高要求的小伙伴。如果你有自建MySQL、Redis、Nginx等服务的需求,一定不要错过这个机会。赶紧去看看吧! 什么是华为云Flexus X实例 华为云Flexus X实例云服务是新一代开箱即用、体

『功能项目』战士的平A特效【35】

我们打开上一篇34武器的切换实例的项目, 本章要做的事情是在战士的每次按A键时在指定位置生成一个平A特效 首先将之前下载的技能拖拽至场景中 完全解压缩后重命名为AEffect 拖拽至预制体文件夹 进入主角动画的战士动画层级 双击第一次攻击 选择Animation 创建事件 创建的动画事件帧放在攻击动画挥剑指定处 命名为PerpetualAtt

第49课 Scratch入门篇:骇客任务背景特效

骇客任务背景特效 故事背景:   骇客帝国特色背景在黑色中慢慢滚动着! 程序原理:  1 、 角色的设计技巧  2 、克隆体的应用及特效的使用 开始编程   1、使用 黑色的背景: ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/7d74c872f06b4d9fbc88aecee634b074.png#pic_center)   2

Weex入门教程之4,获取当前全局环境变量和配置信息(屏幕高度、宽度等)

$getConfig() 获取当前全局环境变量和配置信息。 Returns: config (object): 配置对象;bundleUrl (string): bundle 的 url;debug (boolean): 是否是调试模式;env (object): 环境对象; weexVersion (string): Weex sdk 版本;appName (string): 应用名字;

一款支持同一个屏幕界面同时播放多个视频的视频播放软件

GridPlayer 是一款基于 VLC 的免费开源跨平台多视频同步播放工具,支持在一块屏幕上同时播放多个视频。其主要功能包括: 多视频播放:用户可以在一个窗口中同时播放任意数量的视频,数量仅受硬件性能限制。支持多种格式和流媒体:GridPlayer 支持所有由 VLC 支持的视频格式以及流媒体 URL(如 m3u8 链接)。自定义网格布局:用户可以配置播放器的网格布局,以适应不同的观看需求。硬