十种图像模糊算法的总结与实现
作者:毛星云,騰訊 IEG 游戲開(kāi)發(fā)工程師
后處理(Post-Processing),在圖形學(xué)和游戲開(kāi)發(fā)等領(lǐng)域是提升最終畫(huà)面呈現(xiàn)品質(zhì)的重要渲染技術(shù)。后處理渲染技術(shù)的好壞,往往決定了游戲畫(huà)面是否能夠達(dá)到令人驚艷的級(jí)別。
圖像模糊算法在后處理渲染領(lǐng)域中占據(jù)著重要的地位。很多產(chǎn)品級(jí)后處理的實(shí)現(xiàn),都會(huì)直接或間接依賴(lài)于圖像模糊算法中的一種或多種。無(wú)論是基于高斯模糊(Gaussian Blur)或其改進(jìn)算法的Bloom特效,還是基于徑向模糊(Radial Blur)的Sun Shaft(God Ray),或是基于方向模糊(Directional Blur)的鏡頭眩光光暈(Glare Lens Flare),抑或是景深(Depth of Field)特效中攝影級(jí)失焦感的散景模糊(Bokeh Blur),都以模糊算法作為重要的支撐。所以說(shuō),后處理中所采用模糊算法的優(yōu)劣,決定了后處理管線(xiàn)最終的渲染品質(zhì)和消耗性能的多少。
本文將對(duì)后處理管線(xiàn)中會(huì)使用到的如下十種模糊算法進(jìn)行總結(jié)、對(duì)比和盤(pán)點(diǎn),以及提供了這十種模糊算法以及其衍生算法對(duì)應(yīng)的Unity Post Processing Stack v2版本的實(shí)現(xiàn):
高斯模糊(Gaussian Blur)
方框模糊(Box Blur)
Kawase模糊(Kawase Blur)
雙重模糊(Dual Blur)
散景模糊(Bokeh Blur)
移軸模糊(Tilt Shift Blur)
光圈模糊(Iris Blur)
粒狀模糊(Grainy Blur)
徑向模糊(Radial Blur)
方向模糊(Directional Blur)
另外,本文暫不涉及運(yùn)動(dòng)模糊(Motion Blur),因?yàn)槠渲饕饔糜趲g的運(yùn)動(dòng)變化,不屬于靜態(tài)型模糊。還有一些其他的模糊算法由于不太適用于實(shí)時(shí)渲染,本文也暫不涉及,如Moving Averages filter。
下面先放一組使用了依賴(lài)于模糊算法的后處理特效的實(shí)時(shí)渲染截圖,然后開(kāi)始我們的正文。
圖《巫師2》 中基于徑向模糊(Radial Blur)的Sun Shaft
圖 UE4場(chǎng)景中,間接基于高斯模糊(Gaussian Blur)的Bloom特效給畫(huà)面帶了更好的光感 @ UE4 CyberNeon @Junliang Zhang
圖 Sun Shaft Forest @UE4
圖 《鬼泣5》中的鏡頭眩光光暈(Glare Lens Flare)
圖 Tom Clancys The Division中的基于散景模糊(Bokeh Blur)的景深
這里也放一個(gè)《賽博朋克:霓虹中國(guó)(CyberNeon)》的視頻(ArtStation原貼:artstation.com/artwork/),其中對(duì)于賽博朋克風(fēng)夜中國(guó)風(fēng)城市的展現(xiàn),如果缺少了Bloom和Glare Lens Flare等依賴(lài)于本文講到的模糊算法的后處理特效,展現(xiàn)出來(lái)的品質(zhì)將少了很多韻味:
https://www.youtube.com/watch?v=CZ4MOBSx2xw
十種圖像模糊算法橫向?qū)Ρ?br />
在展開(kāi)全文,對(duì)這十種圖像模糊算法進(jìn)行分別介紹之前,這一節(jié)中先做一個(gè)總覽,即一個(gè)橫向的對(duì)比。要評(píng)判一種模糊算法的好壞,主要有三個(gè)標(biāo)準(zhǔn):
模糊品質(zhì)(Quality)?。模糊品質(zhì)的好壞是模糊算法是否優(yōu)秀的主要指標(biāo)。
模糊穩(wěn)定性(Stability)?。模糊的穩(wěn)定性決定了在畫(huà)面變化過(guò)程中,模糊是否穩(wěn)定,不會(huì)出現(xiàn)跳變或者閃爍。
性能(Performance)?。性能的好壞是模糊算法是否能被廣泛使用的關(guān)鍵所在。
以下是本文涉及的十種模糊算法在標(biāo)準(zhǔn)情況下以上述三個(gè)指標(biāo)作為評(píng)判標(biāo)準(zhǔn)的橫向?qū)Ρ?#xff1a;
從上表的對(duì)比可以看到,除了Grainy Blur因其模糊質(zhì)感的特殊性獲得了“一般”的模糊品質(zhì)評(píng)級(jí)之外,另外九種模糊算法在模糊品質(zhì)和穩(wěn)定性這兩方面都獲得了不錯(cuò)的評(píng)級(jí)。這是因?yàn)榻o到足夠的迭代次數(shù),且不做RT的DownSample,他們都可以收斂到一個(gè)高品質(zhì)的模糊質(zhì)感。
最終的分化在于性能,這才是評(píng)判一種算法性?xún)r(jià)比是否高,能否廣泛用于實(shí)時(shí)渲染的關(guān)鍵因素。其中,可以看到僅雙重模糊(Dual Blur)和粒狀模糊(Grainy Blur)兩種算法,獲得了高的性能評(píng)級(jí)。當(dāng)然,這是針對(duì)標(biāo)準(zhǔn)的算法而言,其他八種算法如果進(jìn)行進(jìn)一步的性能優(yōu)化,也能具有更佳的性能。
關(guān)于X-PostProcessing Libray
X-PostProcessing Libray,簡(jiǎn)稱(chēng)XPL,是本人開(kāi)發(fā)的Unity引擎下的高品質(zhì)開(kāi)源后處理算法庫(kù),旨在提供業(yè)界主流的高品質(zhì)后處理特效的完整解決方案,目前已完美支持Unity Post-processing Stack v2。后續(xù)也將提供對(duì)Unity引擎URP/LWRP/HDRP的兼容支持。
【GitHub地址】:
https://github.com/QianMo/X-PostProcessing-Library
截止本文發(fā)表,目前已以開(kāi)源形式放出了17種Blur算法的后處理實(shí)現(xiàn)。而隨著后續(xù)更多內(nèi)容的公開(kāi),X-PostProcessing Libray將成型為一個(gè)具有100+種后處理特效的高品質(zhì)后處理開(kāi)源算法庫(kù)。
OK,下面我們開(kāi)始正文。先從最熱門(mén),最為大眾所熟知的高斯模糊開(kāi)始。
一、高斯模糊(Gaussian Blur)
高斯模糊(Gaussian Blur),也叫高斯平滑(Gaussian smoothing),作為最經(jīng)典的模糊算法,一度成為模糊算法的代名詞。
高斯模糊在圖像處理領(lǐng)域,通常用于減少圖像噪聲以及降低細(xì)節(jié)層次,以及對(duì)圖像進(jìn)行模糊,其視覺(jué)效果就像是經(jīng)過(guò)一個(gè)半透明屏幕在觀察圖像。
從數(shù)字信號(hào)處理的角度看,圖像模糊的本質(zhì)一個(gè)過(guò)濾高頻信號(hào),保留低頻信號(hào)的過(guò)程。過(guò)濾高頻的信號(hào)的一個(gè)常見(jiàn)可選方法是卷積濾波。從這個(gè)角度來(lái)說(shuō),圖像的高斯模糊過(guò)程即圖像與正態(tài)分布做卷積。由于正態(tài)分布又叫作“高斯分布”,所以這項(xiàng)技術(shù)就叫作高斯模糊。而由于高斯函數(shù)的傅立葉變換是另外一個(gè)高斯函數(shù),所以高斯模糊對(duì)于圖像來(lái)說(shuō)就是一個(gè)低通濾波器。
用于高斯模糊的高斯核(Gaussian Kernel)是一個(gè)正方形的像素陣列,其中像素值對(duì)應(yīng)于2D高斯曲線(xiàn)的值。
圖 一個(gè)典型的高斯核
圖像中的每個(gè)像素被乘以高斯核,然后將所有這些值相加,得到輸出圖像中此處的值。
N維空間高斯模糊方程可以表示為:
在二維空間定義為:
其中??為模糊半徑
下圖為高斯函數(shù)的3維圖示:
高斯模糊也可以在二維圖像上對(duì)兩個(gè)獨(dú)立的一維空間分別進(jìn)行計(jì)算,即滿(mǎn)足線(xiàn)性可分(Linearly separable)。這也就是說(shuō),使用二維矩陣變換得到的效果也可以通過(guò)在水平方向進(jìn)行一維高斯矩陣變換加上豎直方向的一維高斯矩陣變換得到。從計(jì)算的角度來(lái)看,這是一項(xiàng)有用的特性,因?yàn)檫@樣只需要??的計(jì)算復(fù)雜度,而原先的計(jì)算復(fù)雜度為??,其中M, N是需要進(jìn)行濾波的圖像的維數(shù),m、n是濾波器的維數(shù)。
以下為一個(gè)Gaussian Kernel的線(xiàn)性分解過(guò)程:
而下圖很好的對(duì)Gaussian Kernel的線(xiàn)性可分進(jìn)行了描述:
實(shí)現(xiàn)方面,可以采用經(jīng)過(guò)線(xiàn)性分解的高斯核的方案,且用乒乓RT交互blit的方法。高斯模糊對(duì)應(yīng)的Fragment Shader的實(shí)現(xiàn)為:
float4 FragGaussianBlur(v2f i): SV_Target {half4 color = float4(0, 0, 0, 0);color += 0.40 * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);color += 0.15 * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv01.xy);color += 0.15 * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv01.zw);color += 0.10 * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv23.xy);color += 0.10 * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv23.zw);color += 0.05 * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv45.xy);color += 0.05 * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv45.zw);return color; }篇幅原因,在這里以及后文中,對(duì)應(yīng)后處理的Runtime + Shader的完整的實(shí)現(xiàn)就不貼了,但會(huì)給出XPL中的實(shí)現(xiàn)鏈接。
完整高斯模糊的Runtime + Shader實(shí)現(xiàn)可見(jiàn):
https://github.com/QianMo/X-PostProcessing-Library/tree/master/Assets/X-PostProcessing/Effects/GaussianBlur
以下是開(kāi)啟高斯模糊后處理前后的對(duì)比圖:
以及展示了BlurRadius為3,Iteration為6,RTDownScale為1的設(shè)置下,經(jīng)過(guò)橫縱線(xiàn)性分解的高斯模糊的渲染過(guò)程的動(dòng)圖:
對(duì)模糊半徑(Blur Radius)參數(shù)的調(diào)節(jié),可以控制高斯模糊的程度:
二、方框模糊(Box Blur)
方框模糊(Box Blur),又常被稱(chēng)為盒式模糊,其中所得到的圖像中的每個(gè)像素具有的值等于其鄰近的像素的輸入圖像中的平均值。和高斯模糊一樣,Box Blur也是低通濾波器的一種形式。在圖像處理領(lǐng)域,Box Blur通常用于近似高斯模糊。因?yàn)楦鶕?jù)中心極限定理,重復(fù)應(yīng)用Box Blur可以得到和高斯模糊非常近似的模糊表現(xiàn)。
可以將3 x 3的box blur的kernel表示為如下矩陣
而2x2的box blur的kernel表示為如下矩陣:
Box Blur和高斯模糊的性質(zhì)對(duì)比可見(jiàn)下圖:
圖 3D結(jié)構(gòu),2D結(jié)構(gòu)和示例矩陣對(duì)比(a)Box Blur(b)Gaussian Blur
以下是Box Blur的作用過(guò)程的總結(jié):
Box Blur也是線(xiàn)性可分的,如有需要,也可以借助其此性質(zhì),如下所示:
另外box blur也有不少擴(kuò)展與變體,比如Tent Blur(兩次Box Blur)、Quadratic Blur(三次Box Blur)等,具體本文暫時(shí)就不展開(kāi)了。
其中,Tent Blur也已在XPL中進(jìn)行了實(shí)現(xiàn),具體可見(jiàn):
https://github.com/QianMo/X-PostProcessing-Library/tree/master/Assets/X-PostProcessing/Effects/TentBlur
以下是一個(gè)4 x 4的box filter的shader實(shí)現(xiàn),low level optimize方面,可以采用乘加組合的書(shū)寫(xiě)方式,即MAD指令友好的形式,以在部分GPU上實(shí)現(xiàn)指令數(shù)的優(yōu)化:
half4 BoxFilter_4Tap(TEXTURE2D_ARGS(tex, samplerTex), float2 uv, float2 texelSize) {float4 d = texelSize.xyxy * float4(-1.0, -1.0, 1.0, 1.0);half4 s = 0;s = SAMPLE_TEXTURE2D(tex, samplerTex, uv + d.xy) * 0.25h; // 1 MULs += SAMPLE_TEXTURE2D(tex, samplerTex, uv + d.zy) * 0.25h; // 1 MADs += SAMPLE_TEXTURE2D(tex, samplerTex, uv + d.xw) * 0.25h; // 1 MADs += SAMPLE_TEXTURE2D(tex, samplerTex, uv + d.zw) * 0.25h; // 1 MADreturn s; }Box Blur完整的Runtime + Shader實(shí)現(xiàn)可見(jiàn):
https://github.com/QianMo/X-PostProcessing-Library/tree/master/Assets/X-PostProcessing/Effects/BoxBlur
另外也可以考慮將uv計(jì)算放到vertex層。
Box Blur的渲染效果接近高斯模糊,但性?xún)r(jià)比并不高,需要較多的迭代次數(shù)才能達(dá)到高品質(zhì)的模糊效果:
以下是Box Blur在BlurRadius為1.6,Iteration為6,RTDownScale為1的設(shè)置下模糊過(guò)程的動(dòng)圖:
三、Kawase模糊(Kawase Blur)
Kawase Blur于Masaki Kawase 在GDC2003的分享《Frame Buffer Postprocessing Effects in DOUBLE-S.T.E.A.L (Wreckless)》中提出。Kawase Blur最初用于Bloom后處理特效,但其可以推廣作為專(zhuān)門(mén)的模糊算法使用,且在模糊外觀表現(xiàn)上與高斯模糊非常接近。Kawase Blur的思路是對(duì)距離當(dāng)前像素越來(lái)越遠(yuǎn)的地方對(duì)四個(gè)角進(jìn)行采樣,且在兩個(gè)大小相等的紋理之間進(jìn)行乒乓式的blit。創(chuàng)新點(diǎn)在于,采用了隨迭代次數(shù)移動(dòng)的blur kernel,而不是類(lèi)似高斯模糊,或box blur一樣從頭到尾固定的blur kernel。
實(shí)踐數(shù)據(jù)表明,在相似的模糊表現(xiàn)下,Kawase Blur比經(jīng)過(guò)優(yōu)化的高斯模糊的性能約快1.5倍到3倍。
具體思路是在runtime層,基于當(dāng)前迭代次數(shù),對(duì)每次模糊的半徑進(jìn)行設(shè)置,而Shader層實(shí)現(xiàn)一個(gè)4 tap的Kawase Filter即可:
half4 KawaseBlur(TEXTURE2D_ARGS(tex, samplerTex), float2 uv, float2 texelSize, half pixelOffset) {half4 o = 0;o += SAMPLE_TEXTURE2D(tex, samplerTex, uv + float2(pixelOffset +0.5, pixelOffset +0.5) * texelSize);o += SAMPLE_TEXTURE2D(tex, samplerTex, uv + float2(-pixelOffset -0.5, pixelOffset +0.5) * texelSize);o += SAMPLE_TEXTURE2D(tex, samplerTex, uv + float2(-pixelOffset -0.5, -pixelOffset -0.5) * texelSize);o += SAMPLE_TEXTURE2D(tex, samplerTex, uv + float2(pixelOffset +0.5, -pixelOffset -0.5) * texelSize);return o * 0.25; }完整的Runtime + Shader實(shí)現(xiàn)可見(jiàn):
https://github.com/QianMo/X-PostProcessing-Library/tree/master/Assets/X-PostProcessing/Effects/KawaseBlur
Kawase Blur渲染效果接近高斯模糊,但具有更好的性能:
以下是在初始RT DownScale為1、Iteration為6的設(shè)置下,Dual Kawase Blur的渲染步驟:
同樣,對(duì)模糊半徑(Blur Radius)參數(shù)的調(diào)節(jié),可以控制Kawase模糊的程度:
四、雙重模糊(Dual Blur)
Dual Kawase Blur,簡(jiǎn)稱(chēng)Dual Blur,是SIGGRAPH 2015上ARM團(tuán)隊(duì)提出的一種衍生自Kawase Blur的模糊算法。其由兩種不同的Blur Kernel構(gòu)成,如下圖所示。
相較于Kawase Blur在兩個(gè)大小相等的紋理之間進(jìn)行乒乓blit的的思路,Dual Kawase Blur的核心思路在于blit過(guò)程中進(jìn)行降采樣和升采樣,即對(duì)RT進(jìn)行了降采樣以及升采樣。如下圖所示:
由于靈活的升降采樣帶來(lái)了blit RT所需計(jì)算量的減少等原因, Dual Kawase Blur相較于上文中提到的Gauusian Blur、Box Blur、Kawase Blur等Blur算法,有更好的性能,下圖是相同條件下的性能對(duì)比。
可以看到,Dual Kawase Blur具有最佳的性能表現(xiàn)。
為了帶來(lái)更好的性能表現(xiàn),可以將uv的偏移放在Vert Shader中進(jìn)行,而Fragment Shader中基本上僅進(jìn)行采樣即可。
Dual Kawase Blur的Fragment Shader實(shí)現(xiàn)為:
half4 Frag_DownSample(v2f_DownSample i): SV_Target {half4 sum = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv) * 4;sum += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv01.xy);sum += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv01.zw);sum += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv23.xy);sum += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv23.zw);return sum * 0.125; }half4 Frag_UpSample(v2f_UpSample i): SV_Target {half4 sum = 0;sum += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv01.xy);sum += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv01.zw) * 2;sum += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv23.xy);sum += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv23.zw) * 2;sum += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv45.xy);sum += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv45.zw) * 2;sum += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv67.xy);sum += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv67.zw) * 2;return sum * 0.0833; }完整的Runtime + Shader實(shí)現(xiàn)可見(jiàn):
https://github.com/QianMo/X-PostProcessing-Library/tree/master/Assets/X-PostProcessing/Effects/DualKawaseBlur
XPL中也提供了啟發(fā)自Dual Kawase Blur的Dual Gaussian Blur、Dual Box Blur、Dual Tent Blur的實(shí)現(xiàn)。
Dual Gaussian Blur:X-PostProcessing/Effects/DualGaussianBlur
Dual Box Blur:X-PostProcessing/Effects/DualBoxBlur
Dual Tent Blur:X-PostProcessing/Effects/DualTentBlur
Dual Kawase Blur最終的模糊效果截圖如下,可以看到其與高斯模糊的模糊表現(xiàn)也非常接近:
以下是在初始RT DownScale為1、Iteration為5的設(shè)置下,Dual Kawase Blur的渲染步驟:
同樣,對(duì)模糊半徑(Blur Radius)參數(shù)的調(diào)節(jié),可以控制Dual Kawase Blur模糊的程度:
五、散景模糊(Bokeh Blur)
散景(Bokeh)亦稱(chēng)焦外成像,是一個(gè)攝影名詞,一般表示在景深較淺的攝影成像中,落在景深以外的畫(huà)面,會(huì)有逐漸產(chǎn)生松散模糊的效果。散景效果有可能因?yàn)閿z影技巧或光圈孔形狀的不同,而產(chǎn)生各有差異的效果。例如鏡頭本身的光圈葉片數(shù)不同(所形成的光圈孔形狀不同),會(huì)讓圓形散景呈現(xiàn)不同的多角形變化。此外,反射式鏡頭焦外的散景,會(huì)呈現(xiàn)獨(dú)有的甜甜圈形狀。
圖 不同相機(jī)參數(shù)下得到的不同散景模糊(Bokeh Blur)
散景(Bokeh)在攝影學(xué)中被稱(chēng)為焦外成像,而在光學(xué)上被稱(chēng)為Circle of Confusion, CoC(彌散圓/散光圈/散射圓盤(pán) ),即下圖橙色I(xiàn)mage Plane 中的藍(lán)色C所示區(qū)域。由于不同的物距(物體到鏡頭的距離)投影到鏡頭所形成的焦點(diǎn)不同,但I(xiàn)mage Plane 只能放在某個(gè)點(diǎn)上,所以就形成了Circle of Confusion, CoC(彌散圓)。
圖 散景(Bokeh)成因 (圖片來(lái)自GPU Gems 1)
圖 散景(Bokeh)大小不同的成因,即Circle of Confusion, CoC(彌散圓)的大小與人眼分辨率不同的區(qū)域。
鏡頭本身的光圈葉片數(shù)不同(所形成的光圈孔形狀不同),會(huì)讓散景形狀呈現(xiàn)不同的多角形變化。從最初的多邊形,過(guò)渡到最終的圓形。
圖 不同光圈葉片數(shù)的鏡頭,決定了不同的散景形狀
圖 不同光圈葉片數(shù)的鏡頭,決定了不同的散景形狀
圖 不同光圈數(shù)值的鏡頭形態(tài),決定了不同的散景形態(tài)
從上圖可以看出, 由于光圈大小和葉片數(shù)量的不同,散景(Bokeh)的形態(tài)各異。
在圖形學(xué)領(lǐng)域模擬散景(Bokeh)的方法有很多,本文將以最標(biāo)準(zhǔn)的圓形散景為例,采用Golden angle(en.wikipedia.org/wiki/G)的思路進(jìn)行散景模糊(Bokeh Blur)算法的實(shí)現(xiàn)。
具體而言,算法思路是基于對(duì)大量離散螺旋型(spiral)分布的點(diǎn)的渲染,來(lái)模擬出圓形Bokeh的形狀。
核心的Shader算法實(shí)現(xiàn)為:
half4 BokehBlur(VaryingsDefault i) {half2x2 rot = half2x2(_GoldenRot);half4 accumulator = 0.0;half4 divisor = 0.0;half r = 1.0;half2 angle = half2(0.0, _Radius);for (int j = 0; j < _Iteration; j++){r += 1.0 / r;angle = mul(rot, angle);half4 bokeh = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, float2(i.texcoord + _PixelSize * (r - 1.0) * angle));accumulator += bokeh * bokeh;divisor += bokeh;}return accumulator / divisor; }即對(duì)于每一次迭代,讓采樣uv旋轉(zhuǎn)一個(gè)角度,經(jīng)過(guò)足夠次數(shù)的迭代后,眾多以圓形分散開(kāi)來(lái)的點(diǎn),將一起組成合適的Bokeh形狀。
完整的Runtime + Shader實(shí)現(xiàn)可見(jiàn):
https://github.com/QianMo/X-PostProcessing-Library/tree/master/Assets/X-PostProcessing/Effects/BokehBlur
下圖為最終實(shí)現(xiàn)的效果圖:
不同模糊半徑(Blur Radius)變化,可以控制不同的Bokeh半徑的變化:
六、移軸模糊 (Tilt Shift Blur)
移軸模糊(Tilt Shift Blur),又稱(chēng)鏡頭模糊(Lens Blur) ,是源自攝影領(lǐng)域的一種模糊算法。
在攝影領(lǐng)域,移軸攝影(Tilt-Shift Photography)泛指利用移軸鏡頭創(chuàng)作的作品,所拍攝的照片效果就像是縮微模型一樣,非常特別。移軸鏡頭的作用,本來(lái)主要是用來(lái)修正以普通廣角鏡拍照時(shí)所產(chǎn)生出的透視問(wèn)題,但后來(lái)卻被廣泛利用來(lái)創(chuàng)作變化景深聚焦點(diǎn)位置的攝影作品。移軸鏡攝影是將真實(shí)世界拍成像假的一樣,使照片能夠充分表現(xiàn)出“人造都市”的感覺(jué)。
圖 移軸攝影作品
在后處理渲染中進(jìn)行移軸攝影的模擬,可以采用Grident uv算法控制畫(huà)面區(qū)域模糊強(qiáng)度,配合全屏模糊算法的方式來(lái)實(shí)現(xiàn)。
采用Grident uv算法控制畫(huà)面區(qū)域模糊強(qiáng)度的Shader核心實(shí)現(xiàn)如下:
float TiltShiftMask(float2 uv) {float centerY = uv.y * 2.0 - 1.0 + _Offset; // [0,1] -> [-1,1]return pow(abs(centerY * _Area), _Spread); }得到的屏幕模糊強(qiáng)度的mask圖如下:
接著,配合合適的全屏圖像模糊算法,如Bokeh Blur,便可以營(yíng)造出移軸攝影的畫(huà)面感:
完整的Runtime + Shader實(shí)現(xiàn)可見(jiàn):
https://github.com/QianMo/X-PostProcessing-Library/tree/master/Assets/X-PostProcessing/Effects/TiltShiftBlurV2
這里也有了另一個(gè)版本的實(shí)現(xiàn):
https://github.com/QianMo/X-PostProcessing-Library/tree/master/Assets/X-PostProcessing/Effects/TiltShiftBlur
對(duì)模糊半徑(Blur Radius)參數(shù)的調(diào)節(jié),可以用于控制移軸Bokeh半徑的變化:
對(duì)模糊半徑(Blur Radius)參數(shù)的調(diào)節(jié),可以用于控制移軸Bokeh半徑的變化:
在一定的區(qū)域平滑度(Area Smooth)設(shè)置下,調(diào)節(jié)區(qū)域尺寸(Area Size)可以控制移軸模糊區(qū)域的變化:
七、光圈模糊(Iris Blur)
光圈模糊(Iris Blur)是Photoshop CS6中新增的功能,用于模擬淺景深的效果。
可以根據(jù)用戶(hù)不同的輸入?yún)?shù),將普通照片模擬出景深以及散景的效果。(PS: Photoshop中也同樣有Tilf-Shift Blur功能)
圖 Photoshop中的光圈模糊(Iris Blur)功能
圖 Photoshop中的光圈模糊(Iris Blur)功能
在后處理渲染中進(jìn)行光圈模糊的模擬,可以采用一個(gè)徑向的Grident uv算法沿軸心控制畫(huà)面區(qū)域模糊強(qiáng)度,并配合全屏模糊算法的方式來(lái)實(shí)現(xiàn)。
采用徑向Grident uv算法控制畫(huà)面區(qū)域模糊強(qiáng)度的Shader核心實(shí)現(xiàn)如下:
float IrisMask(float2 uv) {float2 center = uv * 2.0 - 1.0 + _Offset; // [0,1] -> [-1,1] return dot(center, center) * _AreaSize; }得到的屏幕模糊強(qiáng)度的mask圖如下:
同樣,配合合適的全屏圖像模糊算法,如Bokeh Blur,便可以營(yíng)造出移軸攝影的畫(huà)面感:
光圈模糊(Iris Blur)完整的Runtime + Shader實(shí)現(xiàn)可見(jiàn):
https://github.com/QianMo/X-PostProcessing-Library/tree/master/Assets/X-PostProcessing/Effects/IrisBlurV2
這里也有另一個(gè)版本的實(shí)現(xiàn):
https://github.com/QianMo/X-PostProcessing-Library/tree/master/Assets/X-PostProcessing/Effects/IrisBlur
對(duì)模糊半徑(Blur Radius)參數(shù)的調(diào)節(jié),可以用于控制光圈Bokeh半徑的變化:
同樣,調(diào)節(jié)區(qū)域尺寸(Area Size)可以控制光圈模糊區(qū)域的變化:
八、粒狀模糊(Grainy Blur)
粒狀模糊(Grainy Blur)是一種低成本的模糊方法,在單pass下即可有合適的模糊表現(xiàn),性能出色,且其模糊質(zhì)感有點(diǎn)類(lèi)似在畫(huà)面上蒙了一層細(xì)碎的冰霜。
其思路是基于隨機(jī)uv進(jìn)行采樣的抖動(dòng),以對(duì)粗粒度的模糊進(jìn)行模擬。核心算法的Shader實(shí)現(xiàn)如下:
float Rand(float2 n){return sin(dot(n, half2(1233.224, 1743.335)));}half4 GrainyBlur(VaryingsDefault i){half2 randomOffset = float2(0.0, 0.0);half4 finalColor = half4(0.0, 0.0, 0.0, 0.0);float random = Rand(i.texcoord);for (int k = 0; k < int(_Iteration); k ++){random = frac(43758.5453 * random + 0.61432);;randomOffset.x = (random - 0.5) * 2.0;random = frac(43758.5453 * random + 0.61432);randomOffset.y = (random - 0.5) * 2.0;finalColor += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, half2(i.texcoord + randomOffset * _BlurRadius));}return finalColor / _Iteration;}這邊是一個(gè)模糊半徑更大的粒狀模糊(Grainy Blur)的渲染效果:
粒狀模糊(Grainy Blur)完整的Runtime + Shader實(shí)現(xiàn)可見(jiàn):
https://github.com/QianMo/X-PostProcessing-Library/tree/master/Assets/X-PostProcessing/Effects/GrainyBlur
對(duì)模糊半徑(Blur Radius)參數(shù)的調(diào)節(jié),也可以控制粒狀模糊的程度:
九、徑向模糊(Radial Blur)
徑向模糊(Radial Blur)可以給畫(huà)面帶來(lái)很好的速度感,是各類(lèi)游戲中后處理的常客,也常用于Sun Shaft等后處理特效中作為光線(xiàn)投射的模擬。
徑向模糊的原理比較直接,首先選取一個(gè)徑向軸心(Radial Center),然后將每一個(gè)采樣點(diǎn)的uv基于此徑向軸心進(jìn)行偏移(offset),并進(jìn)行一定次數(shù)的迭代采樣,最終將采樣得到的RGB值累加,并除以迭代次數(shù)。
其核心算法的Shader代碼實(shí)現(xiàn)如下:
half4 RadialBlur(VaryingsDefault i) {float2 blurVector = (_RadialCenter - i.texcoord.xy) * _BlurRadius;half4 acumulateColor = half4(0, 0, 0, 0);[unroll(30)]for (int j = 0; j < _Iteration; j ++){acumulateColor += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord);i.texcoord.xy += blurVector;}return acumulateColor / _Iteration; }完整的Runtime + Shader實(shí)現(xiàn)可見(jiàn):
https://github.com/QianMo/X-PostProcessing-Library/tree/master/Assets/X-PostProcessing/Effects/RadialBlur
另外需要注意的是,如果迭代次數(shù)不夠多,而又設(shè)置了較高的Offset值,則會(huì)在屏幕四周出現(xiàn)較為明顯的折痕,但一般情況下都還可以接受:
同樣,對(duì)模糊半徑(Blur Radius)參數(shù)的調(diào)節(jié),可以控制模糊的程度:
十、方向模糊(Directional Blur)
方向模糊(Directional Blur)可以看做是徑向模糊(Radial Blur)的一個(gè)變體。其主要思路是傳入一個(gè)角度,然后在runtime層計(jì)算出對(duì)應(yīng)的矢量方向:
float sinVal = (Mathf.Sin(settings.Angle) * settings.BlurRadius * 0.05f) / settings.Iteration; float cosVal = (Mathf.Cos(settings.Angle) * settings.BlurRadius * 0.05f) / settings.Iteration; sheet.properties.SetVector(ShaderIDs.Direction, new Vector2(sinVal, cosVal));然后,在Shader層,將每一個(gè)采樣點(diǎn)的uv基于此方向進(jìn)行正負(fù)兩次偏移(offset),接著進(jìn)行一定次數(shù)的迭代采樣,最終將采樣得到的RGB值累加,并除以迭代次數(shù),得到最終的輸出。
核心算法的Shader代碼實(shí)現(xiàn)如下:
half4 DirectionalBlur(VaryingsDefault i) {half4 color = half4(0.0, 0.0, 0.0, 0.0);for (int k = -_Iteration; k < _Iteration; k++){color += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord - _Direction * k);}half4 finalColor = color / (_Iteration * 2.0);return finalColor; }完整的Runtime + Shader實(shí)現(xiàn)可見(jiàn):
https://github.com/QianMo/X-PostProcessing-Library/tree/master/Assets/X-PostProcessing/Effects/DirectionalBlur
方向模糊后處理的渲染效果如下:
同樣,對(duì)模糊半徑(Blur Radius)參數(shù)的調(diào)節(jié),可以控制模糊的程度:
而調(diào)節(jié)Angle參數(shù),可以控制模糊旋轉(zhuǎn)的方向:
總結(jié)
本文開(kāi)頭已經(jīng)提到,模糊算法在后處理渲染領(lǐng)域占據(jù)著非常重要的地位。很多產(chǎn)品級(jí)后處理的實(shí)現(xiàn),都會(huì)直接或間接依賴(lài)于一種或多種圖像模糊算法。后處理管線(xiàn)中所采用的模糊算法的優(yōu)劣,決定了產(chǎn)品最終的渲染品質(zhì)和消耗的性能大小。
讓我們重新看一下這十種模糊算法的橫向?qū)Ρ?#xff0c;相信此時(shí),大家對(duì)這十種模糊算法已經(jīng)有了更全面的理解,以及自己的選擇。
參考:
[1] GDC 2003, Frame Buffer Postprocessing Effects in DOUBLE-S.T.E.A.L (Wreckless)
[2] SIGGRAPH 2015, Bandwidth-Efficient Rendering
[3] SIGGRAPH 2001,Fast Image Convolutions
[4] Gonzalez R C, Woods R E. Digital image processing, 4th edn. ISBN: 9780133356724[J]. 2017.
[5] https://computergraphics.stackexchange.com/questions/39/how-is-gaussian-blur-implemented
[6] http://datahacker.rs/opencv-average-and-gaussian-filter/
[7] https://towardsdatascience.com/image-processing-class-egbe443-4-filters-aa1037676130
[8] https://www.zhihu.com/question/20813608/answer/261346592
[9] https://en.wikipedia.org/wiki/Box_blur
[10] https://en.wikipedia.org/wiki/Gaussian_blur
[11] http://blog.marmakoide.org/?p=1
[12] https://developer.nvidia.com/gpugems/gpugems/part-iv-image-processing/chapter-23-depth-field-survey-techniques
[13] https://www.flickr.com/photos/valpil58/9425151785
[14] https://en.wikipedia.org/wiki/Bokeh
[15] https://commons.wikimedia.org/wiki/File:Lenses_with_different_apertures.jpg
[16] https://improvephotography.com/29529/aperture-blades-many-best/
[17] https://www.webucator.com/how-to/how-apply-an-iris-blur-effect-adobe-photoshop.cfm
[18] 題圖來(lái)自:https://www.artstation.com/artwork/Z5RkbZ
總結(jié)
以上是生活随笔為你收集整理的十种图像模糊算法的总结与实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 极速搭建一个个人博客网站
- 下一篇: 你一定听过这些不太标准的技术圈发音...