游戲 Bloom 實(shí)現(xiàn)方法
4.1?Bloom
4.1.1 什么是bloom
輝光效果,模擬攝像機(jī)圖像效果。讓舞臺(tái)有真實(shí)明亮效果

4.1.2 Bloom實(shí)現(xiàn)原理
1.提取原圖較亮區(qū)域(閾值設(shè)定亮度)
示例:比如大于顏色亮度大于1的區(qū)域,都提取出來(lái)
2.使用高斯模糊(提取后)圖像
3.模糊的結(jié)果與原圖混合

實(shí)現(xiàn)Bloom的效果需要有倆個(gè)前提知識(shí)
顏色亮度支持大于1(HDR)
使用高斯模糊算法
擴(kuò)展 Bloom的形成原因
Bloom是什么
https://zhuanlan.zhihu.com/p/76505536

4.1.3 ?HDR與LDR
正常使用的是LDR模式 顏色的取值范圍是(0-1)
LDR(Low Dynamic Range,低動(dòng)態(tài)范圍) RGB range in [0,1]
JPG PNG等格式圖片

HDR(High Dynamic Range,高動(dòng)態(tài)范圍) 可以表示RGB range 可超過(guò) [0,1]的范圍
這樣可以提取更高亮度(超過(guò)1)的區(qū)域產(chǎn)生bloom效果
HDR、EXR格式圖片

注意:如果不使用HDR那提取的顏色范圍只能是在(0-1)的范圍

4.1.4 高斯模糊
通常用它來(lái)減少圖像噪聲以及降低細(xì)節(jié)層次。
數(shù)學(xué)的角度
圖像的高斯模糊過(guò)程就是圖像與正態(tài)分布做卷積。由于正態(tài)分布又叫作高斯分布,所以這項(xiàng)技術(shù)就叫作**高斯模糊**。

卷積
問(wèn)題: 什么是卷積?
參考:https://baike.baidu.com/item/%E5%8D%B7%E7%A7%AF/9411006?fr=aladdin
卷積是一種對(duì)圖像的操作,
卷積是有1緯卷積,2維矩陣,N維矩陣構(gòu)成

1維卷積
計(jì)算過(guò)程: 1維卷積 15+24+33=22 ? 14+23+32=16 ?13+22+3*1=10
2維卷積

簡(jiǎn)單理解:
就是提取原來(lái)的圖形的像素RGB,通過(guò)卷積把圖片模糊掉,在放到現(xiàn)有的像素尺寸。
數(shù)學(xué)運(yùn)算如下:
過(guò)程,把卷積核放到起始像素,依次計(jì)算求和。
注意:計(jì)算過(guò)程需要把卷積核水平翻轉(zhuǎn)180度。


輔助閱讀:卷積究竟卷了啥?——17分鐘了解什么是卷積_嗶哩嗶哩_bilibili
什么!卷積要旋轉(zhuǎn)180度?! - 簡(jiǎn)書(shū) (jianshu.com)

高斯核

問(wèn)題 高斯核維數(shù)的增加,模糊的程度也會(huì)變大,計(jì)算量也越大。
假設(shè)屏幕圖像的寬度和高度為W和H

如果使用一個(gè)N*N的一個(gè)卷積核,計(jì)算那計(jì)算量會(huì)很大。
怎么解決這個(gè)問(wèn)題
二維高斯函數(shù)特點(diǎn):可分離性,將二維高斯函數(shù)拆成兩個(gè)一維高斯函數(shù)以降低計(jì)算量
二維高斯核運(yùn)算:N * N * W * H 次紋理采樣
兩次一維高斯核運(yùn)算:2 * N * W * H 次紋理采樣


這里對(duì)應(yīng)的權(quán)重值就三個(gè)。
4.2 算法演示
4.2.0 實(shí)現(xiàn)思路
在C#中調(diào)用OnRenderImage函數(shù) 獲取當(dāng)前的渲染紋理,
然后將實(shí)現(xiàn)Bloom效果的參數(shù)和渲染出的紋理傳入Shader
在Shader里使用4個(gè)Pass完成計(jì)算
簡(jiǎn)單理解就是實(shí)現(xiàn)上面那個(gè)過(guò)程
第一個(gè)Pass,根據(jù)設(shè)定的閾值提取圖像中高亮的區(qū)域
第二個(gè)Pass,實(shí)現(xiàn)垂直方向的高斯模糊
第三個(gè)Pass, 實(shí)現(xiàn)水平方向的高斯模糊
第四個(gè)Pass,把高斯模糊的圖像和原圖進(jìn)行混合,輸出最后結(jié)果。

擴(kuò)展知識(shí) OnRenderImage函數(shù)
函數(shù)介紹
該函數(shù)允許我們使用著色器濾波操作來(lái)修改最終的圖像,輸入原圖像source,輸出的圖像放在desitination里。
該腳本必須掛載在有相機(jī)組件的游戲?qū)ο笊?,在該相機(jī)渲染完成后調(diào)用OnRenderImage()函數(shù);

資料參考:https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnRenderImage.html
4.2.1 PostEffectsBase類
創(chuàng)建的新腳本需要繼承這個(gè)類,新版本刪掉這個(gè)腳本,可以在網(wǎng)絡(luò)上找到或者自己寫(xiě)一個(gè)。
《入門(mén)精要》P245-246 使用
下方提供 這個(gè)類的腳本源碼
4.2.2 創(chuàng)建C#腳本控制
這個(gè)腳本的繼承上面使用的類

第一部分把Shader數(shù)據(jù)傳遞到腳本控制,前判斷傳入的數(shù)據(jù)是否空
這一部分是計(jì)算輸入的Shader,材質(zhì)是否為空
在準(zhǔn)備一些傳給Shader的參數(shù),
注意:
降采樣系數(shù),越大獲取的圖像越小,處理的模糊像素少,計(jì)算量小。
越小效果越好,

開(kāi)始計(jì)算
使用OnRenderImage函數(shù)
source ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 代表原圖
destination ? ? ? ? ? ? ? ? ? ? ? ? ?代表 模糊后的圖像
擴(kuò)展 什么是雙線性濾波?
在上面的代碼部分,有一段

buffer0的filterMode
在這里引入一個(gè)紋理壓縮的一個(gè)概念。
在導(dǎo)入圖片的時(shí)候,有一個(gè)選項(xiàng),就是FilterMode

FilterMode
當(dāng)該紋理由于3D變換進(jìn)行拉伸時(shí),它將如何被過(guò)濾插值。共有三種選擇:
Point 單點(diǎn)插值,紋理將變得塊狀化(blocky up close)
Bilinear 雙線性插值,紋理將變得模糊(blurry up close)
Trilinear 三線性插值,類似Bilinear,但是紋理還會(huì)在不同的mip水平之間(between the different mip levels)進(jìn)行模糊;
所以設(shè)置儲(chǔ)存的這張圖片的變形方式, 第一步就算完成。

計(jì)算模糊效果
擴(kuò)展 Graphics.Blit函數(shù)
這里使用大量Graphics.Blit函數(shù),那Graphics.Blit函數(shù)的功能是什么?

官方這里介紹,簡(jiǎn)單理解就是輸入一個(gè)原圖,根據(jù)材質(zhì)效果計(jì)算出一張新的圖。
示例
Graphics.Blit(原圖,結(jié)果圖,調(diào)用的材質(zhì),使用材質(zhì)的那個(gè)pass)
這里Pass默認(rèn)-1調(diào)用所有pass
腳本部分完成。
全代碼

4.3 Shader部分
視頻有誤地方
CGINCLUDE ? ?和 ? CGPROGRAM 的區(qū)別問(wèn)題

參考:CGINCLUDE 關(guān)鍵字的作用?
資料參考:?https://www.jianshu.com/p/d5767c2a4017?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation
在 fragBlur 片元著色的時(shí)候,這里需要修改成SV_Target

這個(gè)階段的第二個(gè)問(wèn)題,括號(hào)錯(cuò)誤,會(huì)報(bào)錯(cuò)。

本人就這倆個(gè)地方錯(cuò)誤,導(dǎo)致一直沒(méi)有找到。
修改結(jié)果
解析一下Shader的構(gòu)成
第一部分,Shader需要的屬性,
第二部分,設(shè)置第一個(gè)Pass提取原圖的亮度信息。
在SubShader 里設(shè)置渲染語(yǔ)言
注意:CGINCLUDE 和 ? CGPROGRAM的區(qū)別 ?,
聲明 ?變量。
上面部分定義不同階段的Pass ?,定義里不同的頂點(diǎn)著色器,不同的片元著色器。
現(xiàn)在編寫(xiě),每個(gè)Pass里的頂點(diǎn),片元著色器計(jì)算過(guò)程。
第一個(gè)Pass里,提取越圖的亮度信息。
這里單獨(dú)輸出一下,看一下效果。
默認(rèn)


越接近1越黑。提取的顏色越少
第二和第三個(gè)Pass計(jì)算垂直水平方向的模糊,

高斯模糊卷積核

把上面這部分拆成,垂直和水平方向的倆個(gè)一維的計(jì)算。
這一步是在頂點(diǎn)著色器計(jì)算。
定義高斯模糊的片元著色器函數(shù)
這里注意,視頻有倆個(gè)地方出現(xiàn)了,問(wèn)題,詳細(xì)參考上面。
效果 數(shù)值是0,沒(méi)有模糊的效果。

調(diào)整——數(shù)值是8的時(shí)候

這個(gè)就是模糊后面的結(jié)果。
第4個(gè)Pass合并模糊圖和原圖
創(chuàng)建第4個(gè)Pass,

構(gòu)建頂點(diǎn)片元著色器函數(shù)
完成
全代碼
配置Bloom
把這個(gè)C#腳本掛到攝像機(jī)上面

Shader拖到BloomShader里,調(diào)整數(shù)值。
Bloom效果就有了,
有Bloom效果

無(wú)Bloon效果

4.4 Bloom應(yīng)用
HDR到LDR過(guò)程稱之為色調(diào)映射,Tonemapping
資料參考:https://www.jianshu.com/p/8f29baa34bbc
acs模式的色調(diào)映射效果


總結(jié)
很詳細(xì)的了解到Bloom的實(shí)現(xiàn)方式,以及實(shí)現(xiàn)思路。
學(xué)習(xí)到了,卷積的基礎(chǔ)知識(shí),對(duì)高斯核的拆分,

資料參考
https://github.com/logic-three-body/Unity_Bloom
https://blog.csdn.net/candycat1992/article/details/22794773
https://www.yuque.com/qingyan-bng85/zagg8x/epl3qs