崩壞3角色渲染分析


https://blog.csdn.net/liumazi/article/details/78858811

 

渲染逆向方法:

用Adreno Profiler抓幀, 並且分析其中的OpenGL調用及相關資源(頂點數據、紋理、Shader代碼等)

其中Shader代碼和在Unity里選中Shader並點擊Compile and show code看到的gles3部分類似, 建議轉換成更易於閱讀的形式

 

卡通着色思路:

光照計算仍然是漫反射+高光反射, 其中漫反射是HalfLambert, 高光反射公式來自於Blinn-Phong模型

比較關鍵的點是, 漫反射部分不是漸變的, 而是分了3檔, 以實現卡通風格的層次感, 即所謂的梯度漫反射(Ramped Diffuse)

上圖是還原出來的Unity Shader及渲染結果, 下面簡要介紹一下該Shader的實現細節..

 

Main Color:

主紋理, rgb為基礎顏色, a的作用見下文

 

Bloom Mask:

未使用

 

Light Map:

光照紋理, rgb作用見下文

 

mainColor.a:

主紋理alpha通道, 表示不受光照影響的程度, 為1.0時無論是否有光照影響都為原顏色, 為0.0時僅包含光照計算結果,

如身體和頭發主紋理中, 一些黃色的部分, alpha值較高, 用來保持高亮

從主紋理中分離出來的alpha通道, 見下圖

Avatar_Kiana_C2_Texture_Body_Color_RGB2048_A.png和Avatar_Kiana_C2_Texture_Hair_Color_Common_A.png

以及 輸出-主紋理-A通道.png

 

UsingBloomMask:

材質屬性, 是否使用BloomMask紋理調整不受光照影響的程度, 默認關閉

公式為 mainColor.a *= tex2D(_BloomMaskTex, i.texcoord5.xy).x

注意: 只能減弱或保持原狀, 因為紋理采樣結果在0.0~1.0之間

 

UsingDitherAlpha:

材質屬性, 是否應用alpha抖動, 默認關閉

 

FirstShadowMultColor:

材質屬性, 暗面亮度一, xyz分量分別對應主紋理rgb通道, 值越小越暗, 此處為(0.72941, 0.6, 0.65098)

公式為fristShadowColor = mainColor.rgb * _FirstShadowMultColor.xyz

 

SecondShadowMultColor:

材質屬性, 暗面亮度二, xyz分量分別對應主紋理rgb通道, 值越小越暗, 此處為(0.65098, 0.45098, 0.549019)

公式為secondShadowColor = mainColor.rgb * _SecondShadowMultColor.xyz

 

i.color.r和lightMapColor.g和LightArea和SecondShadow:

頂點顏色r通道和光照紋理g通道, 兩者乘積rgProduct用來做暗面顏色選擇, 公式如下

diffuseColor = rgProduct >= 0.090000033 ? otherColor : shadowColor

otherColor = ((rgProductFix + i.halfLambert) * 0.5 >= _LightArea) ? mainColor.rgb : fristShadowColor

shadowColor = ((rgProduct + i.halfLambert) * 0.5 >= _SecondShadow) ? fristShadowColor : secondShadowColor

 

其中,

rgProductFix是rgProduct經過微調的一個值;

i.halfLambert是半蘭伯特值, 即法線與光線夾角的余弦值映射到0.0~1.0范圍內, 夾角越小值越接近1, 用於表示漫反射部分的強度;

_LightArea和_SecondShadow是材質屬性, 分別為用於選擇 原顏色和暗面一、暗面一和暗面二的閾值;

 

上述公式可理解為,

如果rgProduct非常小的話, 在暗面一和暗面二中選一個; 否則, 在原顏色和暗面一中選一個,

相當於漫反射率不再是根據法線漸變, 而是分了3檔(按閾值選擇), 以此實現卡通風格的層次感,

更進一步地, 當rgProduct非常小的時候, 除非i.halfLambert比較大, 否則選的往往是暗面二

 

下圖1 輸出-明暗分布.png, 其中不同顏色代表了不同的區域, 綠色和黑色是暗面一和暗面二, 白色和紅色是原顏色和暗面一

下圖2 輸出-頂點R通道×光照紋理G通道.png, 其中比較黑的區域正對應了上圖的綠色和黑色區域

 

 

Shininess:

材質屬性, 光澤度, Blinn-Phong光照模型中用於計算高光反射的指數, 用於控制高光區域的亮點大小, 值越大亮點半徑越小

 

lightMapColor.b:

光照紋理b通道, 用於使某些區域更容易出現高光, 因為出現高光的條件是 lightMapColor.b + blinnSpec > 1.0

其中blinnSpec是按照Blinn-Phong光照模型計算出來的高光度, 越大表示高光反射越強,

下圖 ID_118_B.png, 這是頭發的光照紋理b通道, 比較明顯; 以及 ID_113_B.png和 輸出-光照紋理-B通道.png

 

lightMapColor.r和LightSpecColor和SpecMulti:

lightMapColor.r為光照紋理r通道, LightSpecColor和SpecMulti為材質屬性, 共同控制當存在高光時高光的顏色,

公式為 _LightSpecColor.xyz * _SpecMulti * lightMapColor.r

見下圖 ID_113_R.png、ID_118_R.png、輸出-光照紋理-R通道.png

 

最終產生的高光分布: (比想象中弱很多)

 

Color:

材質屬性, 用於調整光照計算結果, 只能調的更弱或者保持原狀,

公式為litColor.xyz = (diffuseColor + specColor) * _Color.xyz;

 

其他輸出圖:

輸出-主紋理-RGB通道.png 和 輸出-頂點色-RGB通道.png

 

 

皮膚shader:

與上述shader類似, 但是沒有BloomMask, 增加了ProbToggle用於調節膚色(未見實際使用), 並且mainColor.a不再有上述作用

 

描邊的實現:

將模型在觀察空間中, 按法線往外擴張, 以剔除正面的方式繪制 (Shader中聲明的頂點屬性是切線, 但實際提交的數據應該還是法線)

下圖 輸出-膨脹方向.png, 其中紅色表示右下, 綠色表示左上, 黃色表示右上, 黑色表示左下, 注意: 只是大概的方向不是絕對的

最終描邊結果 輸出-最終結果.png, 為了更明顯, 描邊顏色設置為了黑色, 游戲中實際的值為(0.4117647, 0.3112941, 0.3768184)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM