一般在表現金屬材質時,除了表面的高光反射外,
我們還會希望金屬表面能反射周圍的環境。
這時就要使用到CubeMap(立方體紋理)。
CubeMap是一個具有6個面的立方體,
每個面上都有貼圖。
當物體在此立方體中,
往前後左右上下看,
就會看到此立方體上6個面的貼圖。
(skybox就是運用這種特性)
為了表現金屬的反射特性,
必須將周圍環境當成貼圖,
如圖
橘色:CubeMap
紅色 入射向量
藍色:頂點法向量
綠色:反射向量
今天我們觀察物體上某一點時,
物體如要將周圍環境傳到我們眼中。
需要經過反射後,將對映到的立方體紋理,貼在自己身上。
這樣觀察的人,就可以看到物體反射周圍環境。
首先反射的方向,可由下式求得:
o.worldRefl =reflect(-o.worldViewDir, o.worldNormal);
reflect函數,可以讓我們將
頂點指向觀察點的反方向為入射角,
並以頂點在世界座標為基準,
來求出反射方向。
當有反射方向後,代入:
fixed3reflection = texCUBE(_Cubemap, i.worldRefl).rgb;
即可找出此worldRefl指向的CubeMap的取樣值。
我們可以自己做一個立方體紋理, 交給此物體來對映自己周圍的環境。
Create --> Legacy --> Cubemap
我們可以自己給它6個面上的貼圖,或是點擊視窗:
GameObject --> Render into Cubemap
然後將物件的位置與我們的cubemap給它,
(注意此時的cubemap的Readable須打勾)
再按下 "Render!"。
這樣就可以得到在某個特定的點上,
所看到的Cubemap。
以上是使用我們指定的Cubemap來取樣,
另外我們也可以對場景中的skybox直接取樣。
在官網的範例中(參考資料),
要對skybox取樣,只需利用:
half4 skyData = UNITY_SAMPLE_TEXCUBE(unity_SpecCube0,i. worldRefl);
half3 skyColor = DecodeHDR(skyData, unity_SpecCube0_HDR);
這skyColor就是取樣值。
不過由下兩張圖來看,
即使skybox換成與Cubemap一樣,
這兩種取樣方式出來的結果,還是不同。
為了看的明顯一點,
2個膠囊體的ambient(環境光)暫不考慮。
由skybox取樣的結果(右邊膠囊體),表面比較模糊。
參考資料:
程式碼: