GDC2004上ATI的一個分享,現在還是大多數移動平台游戲的頭發着色方案。
主要的技術要點:Kajiya-Kay着色模型,Marschner着色模型,多Pass解決深度排序。
Kajiya-Kay着色模型是頭發着色的經典模型,在Real Time Rendering 3th有介紹。這里的着色實現結合了Marschner在SIGGRAPH2003上展示的模型,效果更佳。同時Marschner模型也是UE4在Paragon中使用的頭發着色模型,只不過這里用到的Marschner着色模型的特性比較單一。Kajiya-Kay着色模型作為毛發的入門級模型,本文會比較詳細的介紹。至於Marschner模型,由於本文實現利用的模型特征很表面,真正的Marschner模型涉及到復雜的光路,如果之后會寫UE中的基於物理的頭發着色,會詳細介紹。
本文不是簡單的翻譯,而是加入了一些進階或補充的內容。
——多邊形的頭發建模優勢
1.比線渲染更低的幾何體復雜度——加快深度排序。顯卡廠商Nvidia和ATI都提供了自己的毛發解決方案,Hairworks和TressFx,提供了優秀的物理效果,其對引擎的支持和GPU的要求是局限。
2.能夠更好的整合進美術制作的管線流程中。制作對美術人員沒有任何難度,同時游戲引擎都提供完全的支持。
——多邊形的頭發建模步驟
1.多個面片層疊來近似體現頭發的體積感,在Paragon中,也是使用面片來進行頭發的制作。
2.逐頂點的環境遮蔽來近似自投影效果。目前自投影實現已經不是難題,所以這部分的計算可以忽略。如果要使用環境遮蔽的話,使用目前通用的AO方案,如SSAO,DFAO等。
——需要的紋理要求
1·Base Texture(gayscale):垂直拉伸的噪波貼圖。主要是區分面片上發絲。
2.Alpha Texture(gayscale):透明度貼圖,用於表現頭發絲狀,需要有完全不透明的部分。完全不透明的部分是用於深度寫入的部分,在紋理制作上,發梢區域應該為完全不透明。
3.Specular Shift Texture(gayscale):鏡面反射偏移紋理。用於為頭發的兩個鏡面反射高光提供隨機值。
4.Specular Noise Texture(gayscale):鏡面反射噪波紋理。用於為頭發的次要精美發射高光提供隨機強度遮罩。
以上都是灰度圖,在效果要求不高,即四張紋理可以通用的情況下,可以合成一張RGBA紋理,節約采樣器。
——Kajiya-Kay模型
Kajiya-Kay是一個各向異性的線/纖維光照模型,它使用了頭發的切線,而不是法線來進行光照計算。假設頭發的法線位於切線和視線范圍內的平面上。
Kajiya-Kay模型的原始論文:https://www.cs.drexel.edu/~david/Classes/CS586/Papers/p271-kajiya.pdf
論文的內容主要是使用3D紋理渲染毛發,關於Kajiya-Kay模型,只需要看Lighting model for hair這一節即可。
Kajiya-Kay中,頭發絲被視作圓柱體。光照模型包含兩個部分,分別是漫反射項和鏡面反射項。漫反射項本質是Lambert模型在微小的圓柱體的應用,鏡面反射項則是與Phong鏡面反射模型相似的,同樣為圓柱體做調整的特殊模型。
如下圖所示,介紹Kajiya-Kay模型中用到的數學表示,向量均為單位向量。
t——切線
l——光照向量
e——觀察向量,應該用v更合適
x0——圓柱上的任意一點,也就是發絲上的任意一點
P——垂直於t的屏幕,也是l‘的投影面
l'——l在P上的投影
b——與t,l'垂直的向量
t,l',b為基向量(basis vector),他們互相垂直
計算三個基向量,用於之后的計算。
t——模型切線,資源給出。
l'——normalize(l-dot(t,l)*t) ,l減去l在t上的投影向量,並進行單位化
b——cross(t,l'),t和l’的叉積
之后,我們給出P在x0處圓柱的切面,用於分析漫反射項的計算。
n(θ)——角度為θ的法線向量
漫反射項的計算
我們知道,光在平面上的一點產生漫反射,方向范圍是一個半球,在切面上,就是一個半圓。也就是說,我們只需要在圖中0到π的角度范圍中計算漫反射項。
首先,根據Figure7,我們能得到半圓上的法線分布方程:
n(θ)=bcos(θ)+l'sin(θ)
假設漫反射系數為kd,那么漫反射項就是l·n在0到π的定積分*kd。經過數學計算,我們可以得到漫反射項的計算結果:
Kd*sin(t,l)
鏡面反射項的計算
Phong的原始公式是鏡面反射系數*pow(cos(V,R),鏡面反射指數)。在Kajiya-Kay模型的鏡面反射公式中,將反射向量R用e'來代替。
這是因為在Kajiya-Kay模型中,光照擊中頭發之后,反射方向是沿着切線而不是法線以鏡面反射角度射出的,這樣所有的反射光線均位於以切線為軸線,角度為θ(光照與切線之間的夾角)的圓錐體上。
e'是被包含在圓錐體中的最接近觀察向量的鏡面反射向量,如下圖所示。
可以理解為e'是e在圓錐體上投影
——Marschner模型
Marschner是一個基於頭發散射屬性測量而得到的模型,模型本身比較復雜。這里采用了Marschner模型的兩個觀察結果,主要考慮了頭發生長方向對高光的影響,Paragon的頭發采用的更復雜。
1.主要的鏡面反射高光向發梢偏移。
2.次要的鏡面反射高光向發根偏移,且有色。
這是因為:
主要的鏡面反射高光是R(反射)光路的表現,直接反射了光照。
次要的鏡面反射高光是TRT(透射-反射-透射)光路的表現,它透射進頭發內部(折射+吸收),在頭發內部又反射(反射多次,這里只考慮一次)到空氣中。在這個過程中,光線從頭發透射出去的位置已經與光線擊中頭發透射進的位置產生了偏移,同時因為光線在頭發內部散射而產生了顏色。
——Shader拆解
頂點着色器:將切線,法線,觀察向量,光照向量,環境遮蔽項傳遞給片段着色器。追求效果可以考慮逐像素計算部分向量。
片段着色器:
1.漫反射照明:在沒有適合的自投影下,Kajiya-Kay模型的漫反射項sin(T,L)看起來過亮,這里使用調整的N·L項。
2.兩個偏移的鏡面反射高光:主要鏡面反射高光和次要鏡面反射高光。
2.將以上各項合並到顏色輸出。
——偏移鏡面反射高光
為了沿着頭發長度偏移鏡面反射高光,我們將切線向着法線的方向微移。
假設切線T是從發根指向發梢的向量:
—正的微移值向發梢移動高光。
—負的微移值向發尖移動高光。
從Specular Shift Texture中查找偏移值,避免頭發面片上一致的表現,增加隨機表現。
使用半角向量來計算發絲的鏡面反射高光:
—使用反射向量和觀察向量會增加一點着色器的復雜度。(使用IBL可以完全無視)
兩個高光有不同的顏色,鏡面反射指數和不同的偏移的切線。
使用Specular Noise Texture來調整次要高光。
——近似的深度排序
對於正確的alpha blending顯示,需要從后向前的順序渲染。
對於一個有頭發的頭部,從內到外的繪制順序。
使用靜態索引緩沖從內到外的繪制順序,在預處理時間被計算:
—對相連的組件(頭發絲面皮)而不是單獨的三角形進行分類。
——分類的頭發渲染步驟
Pass1——不透明部分
—開啟alpha test,只通過不透明像素
—關閉背面剔除Cull Off
—開啟深度寫入Zwrite On,深度測試為Ztest Less
Pass2——半透明的背面部分
—開啟alpha test,只通過半透明像素
—開啟背面剔除Cull Back
—關閉深度寫入Zwrite Off,深度測試為Ztest Less
Pass3——半透明的前面面部分
—開啟alpha test,只通過半透明像素
—開啟前面剔除Cull Front
—關閉深度寫入Zwrite Off,深度測試為Ztest Less
第一個Pass用來渲染不透明像素並寫入深度緩沖,因為我們要求alpha貼圖一定要有不透明區域。這樣頭發絲的不透明部分寫入了深度,可以很大的減少排序問題。
第二個Pass和第三個Pass只有剔除設置不同,先渲染背面后渲染前面,一是頭發是雙面顯示的,二是避免半透明像素不正確的前后遮擋關系。
——性能調整
廣泛的使用eary Z剔除可以節省運行昂貴像素着色器。
通常來講,大約一半的頭發會被頭擋在后面看不到:
—先繪制頭。(如果頭部使用更復雜的計算的話,自己權衡吧。)
當alpha test開啟的時候,early Z不能使用:
—用一個十分簡單的Pass只做alpha test。
—對於相同的效果,在子隊列Pass中使用深度測試而不是alpha測試。
early Z剔除節省了可預見的填充開銷。
不過現在移動平台是tiled架構,early Z更多的還是針對PC平台。現在移動平台GPU廣泛使用的是Low Resolution Z的技術。
——優化的渲染步驟
Pass1——深度緩沖
—開啟alpha test,只通過不透明像素
—關閉背面剔除Cull Off
—開啟深度寫入Zwrite On,深度測試為Ztest Less
—禁用顏色緩沖寫入ColorMask RGB
Pass1——不透明部分
—關閉背面剔除Cull Off
—開啟深度寫入Zwrite On,深度測試為Ztest Less
Pass2——半透明的背面部分
—開啟背面剔除Cull Back
—關閉深度寫入Zwrite Off,深度測試為Ztest Less
Pass3——半透明的前面面部分
—開啟前面剔除Cull Front
—關閉深度寫入Zwrite Off,深度測試為Ztest Less
——優缺點
1.可以在低端硬件&移動平台實現一般的頭發渲染效果,性能消耗在可以接受的范圍內。在深度優化相關的方面,可以學習網易《楚留香》的trick,返回黑色的不透明頭發模型+使用各向異性鏡面反射渲染的半透明模型疊加的實現方式,減少Pass。
2.這種制作方式適用於多層面片疊加制作的頭發。對於頭發為有體積的polygon的渲染實現則不適用。