Unity Shader 曲面細分簡介
概念介紹
曲面細分一種對輸入的圖元(三角形、四邊形、線段)進行細化,產生出更多的頂點,使其變得更精細的技術。
這一功能在渲染管線中完成,通常會由顯卡硬件支持。從階段上講它位於頂點着色器之后,像素着色器之前。
它的內部流程分為三部分:可編程的Hull Shader(控制細分參數),不可編程的Generator(細分頂點),可編程的Domain Shader(頂點位置計算)。
因此,它基於頂點着色器階段后的頂點數據,並可以控制生成更多的頂點數據交由像素着色器使用。
作用
曲面細分技術降低了模型精細度要求,在模型制作、存儲、加載上都可帶來節省。
通過曲面細分生成更精細的頂點后,可以應用“置換貼圖”技術來渲染出更加精細、逼真的模型。
置換貼圖不同於法線貼圖修改頂點的法線方向來造成光影錯覺,它會真正修改頂點的位置來產生凹凸感,因此當視線與網格切面方向接近時法線貼圖基本上失效而置換貼圖仍可產生逼真的效果。
例如以下分別是【標准】材質、【未細分僅置換】材質、【固定數目細分置換】材質的效果:
關於Unity支持
unity文檔里只提了Built-in Render Pipeline的Surface Shader支持曲面細分,並且只支持三角形。同時它需要Shader Model 4.6target,因此不支持更老的設備。
官方案例
在使用Surface Shader的前提下使用曲面細分非常簡單,以下的每種細分方法都提供了內置的函數,直接調用就完事。
總的來說是在shader中增加兩個函數:
tessellate:FunctionName
vertex:FunctionName
tessellate聲明的函數返回細分控制參數,這是一個float4類型,前三個值分別表示輸入三角形的三個邊被分成幾段,第四個值是Inside因子,算法使用,不太清楚。
vertex聲明的函數可以拿到細分后的所有頂點,可以在這里修改其位置。
例圖:
不細分,僅頂點置換
和上圖不同之處在於,它只聲明了vertex函數,未聲明tessellate函數,因此它僅在vertex函數中采樣了置換圖然后修改頂點位置。
固定細分和頂點置換
例圖中就是這個示例,它在tessellate函數中返回了一個固定的細分因子,因此它產生的細分數量是固定的。
基於距離的細分和頂點置換
它的效果就是當物體離相機近時細分增多,當離相機遠時細分減少。
它的tessellate函數略有不同了,多了三個參數。這三個參數就是原三角形的三個頂點,里面又調用了UnityDistanceBasedTess方法,這個方法會計算每個頂點與相機的距離,最終生成細分因子。
基於邊長的細分和頂點置換
上面的其於距離細分只能用於所有三角面都差不多大的情況,否則細分就不均勻。
因此,UnityEdgeLengthBasedTess基於邊長生成細分因子,更大的三角形將細分成更多三角形。
Unity還提供了替代方法UnityEdgeLengthBasedTessCull,它會額外計算相機的可視范圍裁剪,減少參與細分的三角形數量,當網格會有很多部分在視野外時,應使用這個方法。
馮氏曲面細分
這個的效果就是會讓細分后的面向網格法線方向外移一點點,這會使得網格變得更加光滑,因此用於low-poly模型時效果不錯。
這個更簡單了,不需要提供vertex函數而是指定了一個tessphong的float值控制強度,Unity自動完成頂點修改。
更多
雖然文檔化的只有Surface Shader,實際上也支持更靈活的頂點\像素shader,只是需要去看Surface Shader的生成代碼總結規律。