這個標題看起來有點奇怪,大部分人覺得shader的主要用途就是為遊戲服務,可惜這最基本的概念卻最容易被忽略。如果你經常訪問這個blog,就知道我已經很久沒有寫任何關於shader的文章了。不是我不再對shader感興趣,就像人人都愛寫GUI程式一樣,shader永遠是遊戲編程最讓人興奮的部分-----可以馬上獲得代碼的直觀視覺反饋,讓人很有成就感。不過當我經曆了一個產品的開發過程,並且開始研究引擎設計以後,有了些不同的看法:)。
當我剛開始學習3D程式,覺得shader很神奇(相信很多人也和我一樣),看了大量關於shader的文章,寫了很多”漂亮”的shader。可惜當正式開發一款產品時卻發現原來寫過的大部分shader都無法使用。Why? 在學習shader的過程中,大部分人寫的程式都只能稱為”demo”,我們使用了最前沿的圖形學演算法,幾百行hlsl代碼,只為實現一種特效。但對對一個完整的產品來說,需要同時在情境中實現大量不同材質/特效,並且讓系統能儘可能在底端硬體上也能跑。結果demo裡的Parallax Occlusion Mappiing需要簡化為Parallax Mapping甚至normal mapping等等。因此,針對遊戲開發的shader必須非常有實用性和可行性,必須對特定遊戲/情境做大量最佳化,而這些都是我們在寫demo時不會想到也無法預料的。
Rule No.1,當為遊戲開發shader時,需要時時把可行性放在第一位,記住這個shader還必須和其他大量shader”共存”,不要讓一個shader拖垮一個系統。
接下來rule No.2,低品質的shader比沒有還要糟! 噢,這看起來和rule No. 1完全矛盾?非也,非也。繼續前面的話題,當你為了滿足系統需要,把某個shader簡化到極限時,相應的問題也就出現了:映像品質會變的非常差,最糟的情況下,也許一個”特效”變為讓玩家討厭的特性。舉個例子來說,自從Doom 3之後,動態陰影就成了遊戲開發的大熱門話題,幾乎所有遊戲都把它作為標準特性之一。但是任何實現過shadow mapping的人都知道,看似簡單的陰影實際上是非常耗費系統資源的。於是,為了讓遊戲支援這樣的特性,我們減小shadow map大小,簡化採樣演算法,結果是雖然得到了動態陰影,效果卻非常差:明顯的鋸齒,抖動和不正確的陰影。沒人喜歡這樣的陰影,明顯的鋸齒只會不停讓玩家覺得討厭。每次遇到這樣的情況,我都會直接在設定裡把陰影關閉。
於是有了rule No.3,把資源用在刀刃上。如果你發現無法在現有資源下很好的實現某種特效,那麼完全刪除這個特性也許是最好的選擇,把節約的資源增加到其他已有特效上。Wow從04年11月發布到去年為止都沒有動態陰影,不過這並不影響它成為世界上最流行的遊戲。幾乎沒有玩家不停要求增加陰影,論壇中更多的是對新情境視覺效果的讚歎和對某個技能特效的討論。在激烈的遊戲中,沒有人會去關心陰影是否正確,更能讓玩家興奮的是釋放技能時華麗的特效和對方受傷出灑出的血液。與其把資源花費在陰影這種出力不討好的特性上,我更願意把技能特效做的華麗,花哨。
最後rule No.4,有個性的shader才是好shader。每次開發shader時,不要以crysis作為你的參考目標,即使你成功達到了crysis的水平,人們也只會說:噢,又一個類似crysis的遊戲。你的shader應該讓遊戲畫面看起來與眾不同。如果玩家一看到畫面,就知道是某某遊戲,那麼你的shader或者更進一步說,你的視覺效果設計就成功了。反觀farcry 2和crysis,獨立提取出一幅畫面之後,你大概很難分清他們來自哪個遊戲,因此,從某種這角度來說,後來者farcry 2是失敗的。
ps: 神啊,今天才看到csdn的blog還有個留言功能,狂汗-_-bbbbb.......
對那些沒有及時回複的留言萬分抱歉>.<