unity 手机 模糊效果_GUI背景模糊效果优化
導(dǎo)語
在游戲界面顯示時(shí),通常會(huì)對背景進(jìn)行模糊,使顯示界面更加清楚。此外,在處理景深(Depth of Field)和泛光(Bloom)等后處理特效時(shí),模糊效果也是必不可少的。本文針對移動(dòng)平臺(tái),結(jié)合實(shí)際項(xiàng)目中遇到的UI背景模糊顯示效果,討論了模糊效果的優(yōu)化解決方案。
為了測試不同方案的實(shí)際模糊性能,新建了一個(gè)較為簡單的測試工程,并使用了2款較為低端的手機(jī)進(jìn)行測試:紅米4,處理器為驍龍625和三星Galaxy C5,處理器為驍龍617。在沒有背景模糊效果時(shí),2款手機(jī)的幀率都穩(wěn)定在60FPS左右。
高斯模糊
說到模糊效果,必然提及高斯模糊。
高斯模糊通常用來減少圖像噪聲,降低細(xì)節(jié)層次和圖像模糊等,其利用高斯濾波函數(shù)處理圖像。
簡單地講,高斯模糊就是對圖像中的每個(gè)像素進(jìn)行加權(quán)平均,利用高斯核函數(shù)對像素周圍的多個(gè)采樣點(diǎn)加權(quán)相加,結(jié)果作為新的像素值。在實(shí)現(xiàn)時(shí),可以預(yù)先計(jì)算歸一化的二維高斯核函數(shù)。當(dāng)采用n階高斯核函數(shù)時(shí),算法的復(fù)雜度是Ο(n2)。
一種常見的優(yōu)化方案是將二維運(yùn)算拆分成兩次一維運(yùn)算,先在水平方向做一維高斯運(yùn)算,再在豎直方向做一次高斯運(yùn)算,以7階二維高斯運(yùn)算為例,二維運(yùn)算需要49次計(jì)算,拆分成兩次一維運(yùn)算只需要14次計(jì)算,大大降低了計(jì)算消耗。
一維0均值高斯函數(shù)數(shù)學(xué)表示如下:
此外,因?yàn)楸尘皥D片本來就要進(jìn)行模糊,沒有必要按照全分辨率進(jìn)行采樣,對背景圖片進(jìn)行降采樣可以提升模糊計(jì)算效率。
最初項(xiàng)目里采用的模糊方案就是優(yōu)化高斯模糊算法。
GrabPass {}Pass{?…?}?//?處理水平方向GrabPass?{}Pass{?…?}?//?處理垂直方向利用2次GrabPass進(jìn)行截屏,截屏結(jié)果一次進(jìn)行水平方向模糊處理,一次進(jìn)行垂直方向模糊處理,2次處理都用了9個(gè)采樣點(diǎn)。由于進(jìn)行了2次截屏,然后進(jìn)行高斯處理,性能消耗挺大的。游戲在一些手機(jī)上開啟模糊時(shí)較為卡頓,性能較差。
利用測試工程進(jìn)行測試,結(jié)果在紅米上幀率只有40FPS,在三星上幀率只有20FPS。可以看到,在低端機(jī)上這樣處理的性能損耗還是很大的,比較嚴(yán)重的影響了游戲體驗(yàn)。
初步優(yōu)化方案就是減少2次處理的采樣點(diǎn)數(shù),從9個(gè)減為7個(gè),并且發(fā)現(xiàn)原來的采樣坐標(biāo)計(jì)算是在fragment shader中計(jì)算,會(huì)對性能產(chǎn)生一定影響,改在vertex shader中計(jì)算,然后傳到fragment shader中。
再次測試,在紅米上幀率提升到46FPS,在三星上仍然只有22FPS,比之前結(jié)果稍好一點(diǎn)。
因?yàn)橐苿?dòng)端使用GrabPass性能消耗較大,考慮只用一次截屏,利用原始高斯模糊算法進(jìn)行測試,因?yàn)樵加?jì)算采樣點(diǎn)數(shù)較多,所以只使用了5階高斯核函數(shù)。
fixed4 col = fixed(0, 0, 0, 0);for?(int?s?=?0;?s?5;?++s){for?(int?t?=?0;?t?5;?++t){half4?uv?=?i.grabuv?+?_GrabTexture_TexelSize?*?half4(s?-?2,?t?-?2,?0,?0)?*?_BlurRadius;col?+=?tex2Dproj(_GrabTexture,?uv)?*?GaussWeight[s][t];}}return?col;測試結(jié)果在紅米上幀率降到20FPS,三星上幀率降到13FPS。果然還是采樣點(diǎn)數(shù)過多,計(jì)算消耗太大。
后來考慮過使用后處理或者RenderTexture,但是這樣會(huì)對前景界面產(chǎn)生影響,不能很好地產(chǎn)生背景模糊效果。
Scriptable?
Render?Pipeline
為了不使用GrabPass,減少性能開銷,嘗試從Unity的渲染管線看看能不能在渲染背景遮罩之前進(jìn)行截屏處理。
在2018年,Unity官方推出了Scriptable Render Pipeline(可編程渲染管線),用戶可以根據(jù)自己項(xiàng)目的實(shí)際需要自定義渲染管線,或者使用官方開放的2個(gè)模板:LightweightRenderPipeline和HighDifinitionRenderPipeline,目前這2個(gè)渲染管線還處于測試當(dāng)中,會(huì)有一些變動(dòng)。在LightweightRP中,可以自定義ScriptableRenderPass,并可以自定義RenderPassEvents,目前預(yù)設(shè)了BeforeRendering,Before/AfterRenderingShadows,Before/AfterRenderingPrepasses,Before/AfterRenderingOpaques,…,AfterRendering等系列事件。
因?yàn)閁I界面都是在Transparent階段進(jìn)行繪制的,如何在背景遮罩之前增加一個(gè)pass進(jìn)行模糊處理,仍未找到一個(gè)好的辦法,可能是我對可編程渲染管線理解尚不深刻,雖然沒有找到方法,還是做個(gè)記錄,后面可以繼續(xù)研究。
Kawase模糊
最后還是采用2個(gè)GrabPass,但是要對高斯模糊算法再次優(yōu)化,后面發(fā)現(xiàn)了一種優(yōu)化高斯模糊算法的Kawase模糊算法。
Kawase模糊算法最先是由Masaki Kawase在GDC2003上提出的,是一種性能優(yōu)于高斯模糊算法,但是模糊效果稍差的解決方案。該算法最初用于泛光效果,效果十分接近高斯模糊。
Kawase濾波器是一個(gè)多通道濾波器,每個(gè)通道都會(huì)利用上一通道的結(jié)果,通過累加足夠的濾波通道逼近高斯濾波器。在每個(gè)通道中,對距離當(dāng)前像素一定距離的矩形范圍的采樣點(diǎn)進(jìn)行平均更新當(dāng)前像素值。處理通道的數(shù)量和距離像素中心的距離可以根據(jù)結(jié)果靈活調(diào)整。
5通道Kawase模糊,采樣距離分別為0, 1, 2, 2, 3
測試采用2個(gè)通道,每個(gè)通道處理4個(gè)采樣點(diǎn),通道采樣距離逐漸增加,具體數(shù)值可以調(diào)整。
采樣代碼如下:
fixed4 col = fixed4(0, 0, 0, 0);col?+=?tex2Dproj(_GrabTexture,?UNITY_PROJ_COORD(i.uvgrab[0]));col?+=?tex2Dproj(_GrabTexture,?UNITY_PROJ_COORD(i.uvgrab[1]));col?+=?tex2Dproj(_GrabTexture,?UNITY_PROJ_COORD(i.uvgrab[2]));col?+=?tex2Dproj(_GrabTexture,?UNITY_PROJ_COORD(i.uvgrab[3]));col?*=?0.25;return?col;測試結(jié)果在紅米上幀率未見明顯下降,在三星上穩(wěn)定在28FPS左右,達(dá)到還算流暢的效果。模糊效果相比高斯模糊稍差一點(diǎn),但是仍然可以接受。Kawase模糊只用4個(gè)采樣點(diǎn),能夠獲得比較不錯(cuò)的模糊效果,是一種不錯(cuò)的解決方案。
最后將項(xiàng)目中使用的9階高斯模糊算法和Kawase模糊算法進(jìn)行實(shí)際對比,如圖所示:
(a)優(yōu)化高斯算法
(b)Kawase算法
從圖中可以看出,Kawase算法的模糊效果稍差于高斯算法,但是考慮到Kawase算法每個(gè)通道只用了4個(gè)采樣點(diǎn),算法消耗明顯降低,模糊效果也是可以接受的,仍是一種不錯(cuò)的模糊方案。
總結(jié)
采用原始高斯模糊算法,雖然只用一次截屏,但是采樣點(diǎn)數(shù)過多,即使只是5階,計(jì)算消耗仍然太高,移動(dòng)端性能承受不了。采用2次截屏方案,優(yōu)化高斯算法分成2次一維模糊處理,大大減少了采樣點(diǎn),性能有所提升,但仍對幀率有較大影響,通道采樣點(diǎn)數(shù)可以根據(jù)模糊效果和機(jī)器性能進(jìn)行選擇,一般采用5個(gè)或7個(gè)采樣點(diǎn);Kawase模糊算法每個(gè)通道只用4個(gè)采樣點(diǎn),減少了計(jì)算消耗,性能最好,并且顯示效果比較接近高斯模糊,是一種不錯(cuò)的模糊方案。
另外,對于Shader編寫有一些常見的優(yōu)化:
1. 使用合適的數(shù)值精度:
0.0-1.0范圍內(nèi)的顏色值通常使用低精度變量fixed表示;
位置數(shù)據(jù)通常使用高精度float;
光照計(jì)算中的法線和向量通常使用中等精度half;
不清楚時(shí),數(shù)據(jù)默認(rèn)采用高精度float。
2. 延后向量計(jì)算
先進(jìn)行標(biāo)量計(jì)算,再進(jìn)行向量計(jì)算
3. 使用Uniforms或Constants變量,而不是在Shader中計(jì)算
4. 避免動(dòng)態(tài)查找
避免在fragment shader中對紋理坐標(biāo)進(jìn)行數(shù)學(xué)計(jì)算,在vertex shader中計(jì)算。
uniform sampler2D textureSampler;fixed4?frag(v2f?i){???half2?modifiedTexCoord?=?half2(1?–?i.vTexCoord.x,?1?–?i.vTexCoord.y);???fixed4?col?=?texture2D(textureSampler,?modifiedTexCoord);return?col;}參考資料
https://blog.csdn.net/poem_qianmo/article/details/51871531
https://software.intel.com/en-us/blogs/2014/07/15/an-investigation-of-fast-real-time-gpu-based-image-blur-algorithms
http://www.daionet.gr.jp/~masa/archives/GDC2003_DSTEAL.ppt
https://developer.apple.com/library/archive/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/BestPracticesforShaders/BestPracticesforShaders.html
-END-
數(shù)天技術(shù)
讓技術(shù)·更有趣
總結(jié)
以上是生活随笔為你收集整理的unity 手机 模糊效果_GUI背景模糊效果优化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 防暴恐演练到的校园第一道生命防线是什么?
- 下一篇: 二战中最好的中型坦克之一—德国黑豹坦克