之前說過立方體貼圖,它是環(huán)境貼圖技術(shù)的一種實現(xiàn)方式,能夠模擬物體周圍環(huán)境,使用了環(huán)境反射的物體可以看起來像表面鍍了一層金屬一樣反射處周圍環(huán)境。反射探針就是基于立方體貼圖實現(xiàn)的一種unity組件。
但是立方體貼圖沒有什么可調(diào)整性,它產(chǎn)生的反射性很強(qiáng)烈,一般只適用于金屬、鏡子等具有強(qiáng)反射特性的材質(zhì),并且開發(fā)者并不能靈活控制它。那么有沒有一種技術(shù),可以靈活控制立方體貼圖技術(shù)的反射性,讓它是適用于任何材質(zhì)的物體呢?
這種技術(shù)就是基于圖像的照明技術(shù)(簡稱IBL)!
IBL的設(shè)置
IBL是基于立方體貼圖技術(shù)改進(jìn)的一種環(huán)境反射技術(shù),它最大的特點是可以靈活控制反射屬性,輕松模擬出物體材質(zhì)光滑、粗糙等特性。這時普通的立方體貼圖技術(shù)難以做到的。
要使用IBL,只需要將cubeMap的Convolution Type屬性 設(shè)置為Specular(Glossy Reflection)。

另外,還需要將過貼圖的過濾模式filter mode設(shè)置為Trilinear(默認(rèn)為Bilinear),Trilinear能夠在不同的mip map層級中進(jìn)行插值計算,這樣保證了每個層級的貼圖過渡效果都很順滑,這是Bilinear無法做到的。

環(huán)境反射模擬的是間接光照,將IBL設(shè)置為Specular,模擬的是間接光照的鏡面反射(高光),如果設(shè)置為Diffuse,IBL將模擬間接光照的漫反射效果。
除了直接設(shè)置立方體貼圖的Convolution Type屬性可以用IBL外,還可以通過添加反射探針烘焙貼圖的方式動態(tài)生成IBL技術(shù)的立方體貼圖。通過烘焙方式生成的IBL貼圖不需要進(jìn)行任何設(shè)置,在烘焙的過程中unity已經(jīng)幫助我們設(shè)置好了

基本原理
IBL并不像cubeMap那樣直接存儲紋理信息,通過將cubeMap的Convolution Type屬性 設(shè)置為Specular(Glossy Reflection),unity為幫助我們做了一個IBL最重要的操作:獲取到環(huán)境貼圖后對它進(jìn)行了一系列離線的光照計算,然后生成了新的光照結(jié)果,并把它存儲在mip map層級中。
也就是說IBL還有一個重新計算光照的過程,也正是因為如此,我們才能對重新計算的光照進(jìn)行調(diào)整,從而模擬出更多的材質(zhì)效果。

IBL 光照計算后的cubeMap,會比計算之前更粗糙一些,這些粗糙度信息分布在每個mip map層級中,通過調(diào)整層級我們可以看到cubeMap的過渡會比計算之前更流暢。

調(diào)整mipMap層級有什么作用呢?
我們知道,區(qū)分材質(zhì)與材質(zhì)的不同,其中一個非常重要的屬性就是粗糙度,通過調(diào)整粗糙度,就能模擬出不同的材質(zhì)效果,而這個mipMap層級的調(diào)整,就能達(dá)到異曲同工的效果。
手動采樣
接下來,我們在shader 中配置一個粗糙度的參數(shù),通過設(shè)置粗糙度來采樣不同層級的mip map,這里使用texCUBElod()方法,對cubeMap進(jìn)行采樣。
_Roughness("Roughness",Range(0,1))= 0.5
float _Roughness;
float mip_Level = _Roughness * 9.0; // mipmap 9個層級
half4 colorCubeMap = texCUBElod(_CubeMap,float4(reflect_dir,mip_Level));
half3 env_hdr_color = DecodeHDR(env_color,unity_SpecCube0_HDR);
cubeMap通常有9個層級,因此在代碼中_Roughness參數(shù) 乘以了一個9.0,這樣就能靈活切換貼圖各個層級的mipMap。
代碼中的unity_SpecCube0_HDR,是unity內(nèi)置的一個專門用于獲取cubeMap貼圖的變量。
通過設(shè)置Roughness參數(shù),就可以調(diào)節(jié)cubeMap的粗糙度,這樣能輕松模擬出金屬、非金屬的材料質(zhì)感

這種方式,適用于自定義IBL貼圖的場景,如果是由反射探針烘焙生成的IBL貼圖,要采用什么方式呢?
自動采樣
要對反射探針自動生成的貼圖采樣,需要使用的unity配置的一個方法UNITY_SAMPLE_TEXCUBE_LOD(),分別傳入unity_SpecCube0(內(nèi)置變量)、反射方向、mipMap層級,這樣就能獲取到基本的顏色貼圖。
之后再對它進(jìn)行解碼操作即可,其他代碼和手動采樣基本一致。
half4 colorCubeMap = UNITY_SAMPLE_TEXCUBE_LOD(unity_SpecCube0,reflect_dir,mip_Level);
half3 env_color = DecodeHDR(colorCubeMap,unity_SpecCube0_HDR);
以上就是IBL技術(shù)的最簡單展示,我們重點要掌握IBL的基本技術(shù)原理,它在Unity中該如何設(shè)置,使用shader如何采樣IBL貼圖。
在實際項目過程中,IBL并不是單獨存在的,它通常還會與光照模型、后期處理技術(shù)結(jié)合一起使用,代碼復(fù)雜度也會加大。