三言兩語說shader(九)鑽石

2021-07-11 06:15:37 字數 3428 閱讀 4009

這次的目標是繪製一顆閃閃發光的鑽石,追求效果是越接近真實越好。

先說說為此我這幾天幹了些什麼。

1.看了stalendp blog裡那篇《鑽石效果》後頭的參考文獻

最有價值的就是ati在2023年gdc上作的演講,題目就叫drawing a diamond。但是由於只有ppt,所以很難重現工程深入學習。思路大概是預備了一張折射cubemap,一張帶模擬色散的反射cubemap,最後再加上耀斑混合而成。

2.試驗了一些簡單的鏡面反射

非實時的cubemap反射最簡單沒什麼好說的,需要注意的是要做到位置精確的鏡面反射還是很難的,一不小心就會發現當物體離反射面很近時,尺寸位置都會嚴重錯誤。

像下圖這樣,球的映象明顯尺寸過大了。

實時獲取環境cubemap的反射也測試了下,沒記錯的話上圖cubemap的facesize設的是512,在我的一加手機上基本就跑不到正常幀了,facesize設成256幀率還可以接受,但畫質就沒法看了,總之實時反射是手機無法承受的。

這裡我總結一點思想:

遊戲畫面表現本身就帶有很多虛假的成分,因為全按真實的來計算效能根本無法承受,最簡單的拿光照來說,不談多次反射的環境光,單純的一次平行光照實時計算都沒法滿足,都要預烘焙光照貼圖,陰影也一樣,真實的計算太費效能,一般也弄個假的完事。

所以我們會發現遊戲畫面和現實**的差距總是一目了然。所以會出現很多專門掩飾的技巧。

如何抓住主要部分,在效果和效能間做出取捨,而又能盡量達到接近真實的效果,大概就是圖形工程師們大多數時候在思考的事情了。

這個鑽石效果的演示demo,明顯要按固定環境的思路來,不需要考慮實時問題,像前面提到的那種尺寸扭曲的問題,基本也是可以忽略的,因為鑽石形狀類似小球,環境的輕微扭曲是能被輕易掩飾過去的。

3.到assetstore搜尋了下相關資源

發現免費的gem shaders就是unity官方提供的,而且還為5.0專門更新過一次。我跑了下它的示例場景,感覺觀感不是很滿意。

主要是它提供的幾個鑽石模型形狀我也不喜歡,於是自己到網上找了個大概是傳說中「八星八箭」形狀的模型,然後還是用這個shader試了下效果,結果發現還是很屌的。

我原本的想法是盡量用真實的光線折射、反射計算得到最終效果的。但是就算暫不考慮**實現,不考慮實現後的效能如何,首先單純就目前憑我有限的光學姿勢能不能建立起真實準確的光學模型都很明顯是成問題的。

所以這次我們還是以學習官方的示例為主,不要整天想自己搞什麼大新聞了。

**如下:

shader "fx/gem"

} subshader

// first pass - here we render the backfaces of the diamonds. since those diamonds are more-or-less

// convex objects, this is effectively rendering the inside of them.

pass ;

v2f vert (float4 v : position, float3 n : normal)

fixed4 _color;

samplercube _refracttex;

half _environmentlight;

half _emission;

half4 frag (v2f i) : sv_target

endcg

} // second pass - here we render the front faces of the diamonds.

pass ;

v2f vert (float4 v : position, float3 n : normal)

fixed4 _color;

samplercube _refracttex;

half _reflectionstrength;

half _environmentlight;

half _emission;

half4 frag (v2f i) : sv_target

endcg

} // shadow casting & depth texture support -- so that gems can

// cast shadows

usepass "vertexlit/shadowcaster"

}}

下面我來分析其中的姿勢點:

個人水平有限很多說法可能是錯的,這裡申明下先。

1.折射光的模擬

首先它的折射光並沒有真實計算,而是給了這樣一張cubemap圖,然後實際上是通過反射在計算。

2.pass設計

大致分兩步,第乙個pass是繪製鑽石的背面,第二個當然就是前面了。注意第二個pass裡的blend one one,表示兩個圖層1:1混合。

考慮到鑽石是個透明的物體,這樣設計也是合情合理的。

3.光照模型設計

大致也是折射光、反射光、環境光、自發光各種疊加各種乘啦。反正因為白色是255,黑色是0,這裡雖說算的是光,但實際處理的還是顏色,不管是加還是乘,都是越疊越亮,符合光線疊加的基本規律。至於它的計算公式是源自準確的光學原理,還是近似的模擬,我當然也不知道啦。

4.hdr

high dynamic range,不負責任的說下,大概就是假如0是黑色,1是白色,那麼有些部分的顏色可以超過1,這樣最終畫面結果會呈現出一種亮處高閃耀的效果,具體請參考unity官方文件說明。

5.菲涅爾效果

簡單說就是因為光線射向玻璃時,一部分被反射,一部分直接射進去了,導致最終反射光線呈現乙個視角越平行於入射面,反射效果越強,越垂直越弱的現象。

第二個pass計算時引入了這個因子。

所以一開始我說自己難以建立準確的模型,比如像這種細微而又真實存在的現象,僅憑一點粗淺的折射反射姿勢而不去深入學習又怎麼能考慮到呢?

這個shader裡用了好多巨集,在cgincludes資料夾裡的那些檔案裡都可以查到,這些我大致可以理解或者叫猜到怎麼回事,但要真正弄清楚肯定得費一番功夫。

這裡請允許豬哥偷個懶,隨便說說裝作懂了的樣子,具體的計算細節就不一一展開了。

結語:至此初階段的shader學習計畫就算完成了,由於我刻意趕了下進度,偷了些懶,比計畫提前了一周。一分耕耘一分收穫,shader這塊水很深,想要有所造詣肯定得花更多的時間。但我出於全盤考慮目前並不想在這塊繼續投放精力。

下一階段目光回到c#語言這塊最基礎的領域,繼續修內力。去年買的《c#本質論》要收尾,一直沒翻的《深入理解c#》也要看完。

談語言難免會牽涉到設計模式,但也盡量避開。

週期定在五周吧。

三言兩語說shader(七)黑幕擴散

按計畫繼續,目前為止寫了三篇對工程已有shader的分析解讀,當然實際上我讀的shader遠不止這三個啦,比如這週就把樂樂同學的blog裡的幾十篇文章泛泛通讀了一遍,主要也是為自己開始構思寫一些簡單的shader作準備,所謂 思而不學則殆 不多看些別人的東西自己就想搞創作明顯是要吃虧的。所謂 黑幕擴...

三言兩語說shader(八)牆體透明

很抱歉這篇文章要放個空彈。計畫寫 牆體透明 的原因,也是工程實際需要,攝像機固定側視主角,但場景是真3d的,所以有時主角會被牆擋住,這時要作一些處理。之前用過一種直接讓人物變色顯示的方案,但效能損耗嚴重,具體原因我還沒分析。個人覺得讓牆體變透明的方案觀感效果可能更好。unity 牆遮擋人物時變為半透...

三言兩語 數學與哲學

起這個話題,是因為看到 中國哲學狂人挑戰世界頂級數學難題四色猜想 為此sohu還作了專題爭鳴。哲學和數學都是人類的基礎科學,古代的大數學家同時也是哲學家,比如 柏拉圖和亞里斯多德。亞里斯多德很早就認為 數學研究的物件是從物理實體上面所引出來的抽象觀念。所以我們可以從接受不存在的負數,到更難理解的虛數...