崩壞三人物渲染分析

2021-08-08 14:28:56 字數 3804 閱讀 3743

崩壞三的圖形渲染是近年來手遊**渲染的標桿,目前市面上的**類手遊很少能望其項背。通常一款受歡迎的遊戲出來很快就有大批同型別的遊戲跟進,但是近一年的時間過去了,還沒有出現效果能媲美崩壞的遊戲,追根溯源還是因為其渲染技術不能被模仿。作為乙個愛好者,為了學習其中的奧秘,特帶著敬意去分析其渲染方法。採用的方法是採用工具抓取了其中一幀資料,然後人肉翻譯了其shader演算法,進而探求其中的奧秘。選取了芽衣這個角色來分析,因為做了很多subshader,在不同效能的裝置上表現效果是不一樣的,本篇使用的是小公尺5作為裝置。

在人物渲染中,採用了高光以及兩層陰影來模擬光照資訊,同時,陰影之間不是採用重合來表現的,採用兩層交錯示(顯示了陰影一就沒有顯示陰影二)。

整個渲染使用了兩張貼圖,一張是主紋理圖,另一張是lightmap;這張lightmap的三個通道分別儲存了高光mask、陰影mask以及高光資訊;

rgb通道儲存值

陰影mask作用是根據其灰度值來控制陰影的交錯顯示,在這張陰影mask圖中,灰度值最大的為138,這有點迷茫,為了配合演算法?

陰影mask

模型是自帶了頂點色的,這個頂點色不是為了調色之類的,而是用來控制陰影的顯示,觀察遊戲主介面中人物的模型,可以發現人物臉上的光照只在某些地方顯示,有些地方是不會出現,這些地方都是使用了頂點色來調節陰影強度,使其更平滑更真實。詳情可以參考公尺哈遊技術總監在unite 2017大會上的[ 演講報告 ].

第一層陰影是根據half lambert光源,頂點色以及陰影mask共同作用的結果,演算法如下:

fixed mask = lightmapcolor.y * i.color.x;

mask += saturate(i.halflambert);

mask = mask *0.5 +(-_lightarea) + 1

;intlightstep = step(1,mask);

maincol.xyz = tex2d(_maintex,i.uv).rgb

;fixed3 firstshadow = maincol.xyz * _firstshadowmultcolor.rgb

;if(lightstep!=0)

firstshadow = maincol.xyz

;else

firstshadow = firstshadow ;

lightmapcolor.y直接顯示控制了陰影顯示的區域,當其灰度值較小時,即顯示第一層陰影。通過引數lightarea來調節顯示陰影的區域大小。同時,為了根據視角的方向來變化陰影,特意加入了half lambert光源強度值,就是為了根據視角來控制陰影的變化。定點色的i.color.x數值用來調節是否顯示陰影。如上分析的那樣, 有些區域比如臉部,某些部位是沒有陰影的,那麼這裡就可以使用頂點色來抑制陰影。

同理,根據第一層陰影的方法,可以獲得第二層陰影:

fixed3 secondshadow = maincol.xyz * _secondshadowmultcolor.rgb

;fixed secmask = i.color

.x * lightmapcolor.y + saturate(i.halflambert);

secmask = secmask *0.5 + (-_secondshadow)+1

;lightstep = step(1, secmask);

if(lightstep !=0)

secondshadow= maincol.xyz

;else

secondshadow= secondshadow;

為了使兩層陰影之間實現過渡,則需要將進行交錯顯示,而不是疊加顯示,**如下:

fixed sep = i.color.x * lightmapcolor.y + 0.9;

int sepmask = step(1,sep);

fixed3finalcolor

if(sepmask != 0)

finalcolor= firstshadow;

else

finalcolor= secondshadow;

高光的計算方式如下:

float3 viewdir = -i.worldpos + _worldspacecamerapos.xyz;

viewdir = normalize(viewdir);

float3 halfview = viewdir + normalize(_worldspacelightpos0.xyz);

halfview = normalize(halfview);

float shinpow = pow(max(dot(normalize(i.worldnormal.xyz), halfview), 0), _shininess);

float oneminusspec = 1 - lightmapcolor.z;

oneminusspec = oneminusspec - shinpow;

int specmaslk = step(0,oneminusspec);

fixed3 speccolor = _specmulti * _lightspeccolor.xyz;

speccolor = lightmapcolor.x * speccolor;

if(specmaslk!=0)

speccolor = 0;

else

speccolor = speccolor;

直接上結果:

對與我這個對美術十竅通了九竅的人來說,實在調不出滿意的顏色(囧o(╯□╰)o);但其陰影效果以及高光效果已經能隨著角色的轉動而變化。再看一下面部:

這張圖是沒對頂點色處理的圖,可以看到,臉部的陰影變化很不自然。為了改變這種彆扭的效果,可以通過修改頂點色值,建立mask來抑制不必要的光影;修改頂點色的方法,一是可以通過模型軟體來修改,但這樣很難立即看到修改後的效果,還有一種方式是直接unity中編寫乙個修改頂點色的工具,這樣能更直觀的修改頂點色;下面的效果是修改頂點色後的結果:

可以看到,臉部的陰影效果變得更加自然;

在崩壞三的角色渲染中,並沒有採用很多高深的渲染技術,而是通過各種非常技巧性的方法來進行渲染的;這讓人聯想到圖形學上的至理:如果它看上去是對的,那麼它就是對的。其沒有使用很多複雜的演算法來表現出滿意效果,而是通過各種trick來實現想要的結果,尤其是在**渲染中,更是各種採用奇技淫巧來實現效果。後續文章中,將繼續這款遊戲中的各種渲染技術。

1088 三人行 (20 分)

子曰 三人行,必有我師焉。擇其善者而從之,其不善者而改之。本題給定甲 乙 丙三個人的能力值關係為 甲的能力值確定是 2 位正整數 把甲的能力值的 2 個數字調換位置就是乙的能力值 甲乙兩人能力差是丙的能力值的 x 倍 乙的能力值是丙的 y 倍。請你指出誰比你強應 從之 誰比你弱應 改之 includ...

1088 三人行 (20 分)

單位 浙江大學 時間限制 400 ms 記憶體限制 64 mb 長度限制 16 kb 子曰 三人行,必有我師焉。擇其善者而從之,其不善者而改之。本題給定甲 乙 丙三個人的能力值關係為 甲的能力值確定是 2 位正整數 把甲的能力值的 2 個數字調換位置就是乙的能力值 甲乙兩人能力差是丙的能力值的 x ...

1088 三人行 (20 分)

子曰 三人行,必有我師焉。擇其善者而從之,其不善者而改之。本題給定甲 乙 丙三個人的能力值關係為 甲的能力值確定是 2 位正整數 把甲的能力值的 2 個數字調換位置就是乙的能力值 甲乙兩人能力差是丙的能力值的 x 倍 乙的能力值是丙的 y 倍。請你指出誰比你強應 從之 誰比你弱應 改之 輸入格式 輸...