使用Unity為數(shù)字人添加逼真的毛發(fā)細(xì)節(jié)

文章來(lái)源: 作者:frank 發(fā)布時(shí)間:2021年10月15日 點(diǎn)擊數(shù):

數(shù)字人技術(shù)現(xiàn)在已經(jīng)是一項(xiàng)比較完善的技術(shù),通過(guò)Unity引擎的烘焙與深度渲染,現(xiàn)在的數(shù)字人已經(jīng)變得相當(dāng)逼真。

在本文中來(lái)自完美世界移動(dòng)項(xiàng)目支持部的徐行跟大家分享了他在完美世界研發(fā)的 Unity 毛發(fā)系統(tǒng)。

“其實(shí)這個(gè)作品還在很初期的階段,還有很大的提升空間,這次主要是讓她幫忙展示一下毛發(fā)。這個(gè)是本工作的大概時(shí)間線,其實(shí)前期還不配被稱(chēng)之為自研毛發(fā)系統(tǒng),只能稱(chēng)得上是一個(gè)英偉達(dá) HairWorks SDK 的集成。隨著后期需求越來(lái)越深入,自研的部分也越來(lái)越多?,F(xiàn)在只是思想上部分參考了 HairWorks,代碼已經(jīng)全部重寫(xiě)了?!毙煨姓f(shuō)道。

現(xiàn)在游戲中比較傳統(tǒng)的毛發(fā)解決方案有兩類(lèi),第一類(lèi)就是網(wǎng)格頭發(fā),這類(lèi)頭發(fā)其實(shí)渲染效果還不錯(cuò),但是往往物理效果不太好,而且也不太適合做短毛。

Uncharted by NaughtyDog

另一類(lèi)是 FurShell,專(zhuān)門(mén)用來(lái)做短毛的。但是湊近了看,層狀瑕疵也非常明顯。做毛發(fā)的終極解決方案,肯定就是基于發(fā)絲的毛發(fā)系統(tǒng)。這是一些有代表性的案例,比如《最終幻想》、《怪獸公司》、《長(zhǎng)發(fā)奇緣》、《古墓麗影》和《巫師 3》。

雖然基于發(fā)絲的方案效果很棒,但是問(wèn)題也是顯而易見(jiàn)的。那就是發(fā)絲數(shù)量太多,導(dǎo)致無(wú)論是物理模擬還是渲染還是存儲(chǔ)等等都有比較大的困難。

HairWorks 是如何應(yīng)對(duì)這些挑戰(zhàn)的呢?這就得從它的資源表示方式講起了。HairWorks 的毛發(fā)資源并不是直接存儲(chǔ)每根發(fā)絲的信息,而是主要存儲(chǔ)了兩個(gè)東西,圖中的黃線被稱(chēng)之為導(dǎo)發(fā),圖中的網(wǎng)格被稱(chēng)為生長(zhǎng)網(wǎng)格。而物理模擬則在導(dǎo)發(fā)上進(jìn)行,發(fā)絲則是導(dǎo)發(fā)間插值出來(lái)的,這樣就能極大的減少計(jì)算量和存儲(chǔ)間的需求。

發(fā)絲具體是怎么插值的呢?其實(shí)生長(zhǎng)網(wǎng)格是由一些三角面構(gòu)成的。生長(zhǎng)網(wǎng)格上面每一個(gè)頂點(diǎn)對(duì)應(yīng)一根導(dǎo)發(fā),隨機(jī)生成一定數(shù)量的重心坐標(biāo),在渲染的時(shí)候就可以利用重心坐標(biāo)作為權(quán)重,在三根導(dǎo)發(fā)間進(jìn)行插值了。

為了讓生成的發(fā)絲更加平滑,在生成發(fā)絲前還可以對(duì)導(dǎo)發(fā)做一些平滑,使用平滑過(guò)的導(dǎo)發(fā)進(jìn)行插值。

物理模擬又是怎么做的呢?HairWorks 選擇了一種非常易于理解的物理模擬方法,也就是質(zhì)點(diǎn)彈簧法。圖中的紅線就是進(jìn)行物理模擬的導(dǎo)發(fā),紅線上的小圓圈就是質(zhì)點(diǎn),發(fā)根處的質(zhì)點(diǎn)是完全受骨骼蒙皮控制的,其他的質(zhì)點(diǎn)則會(huì)受到諸如風(fēng)力、重力等等的影響,也會(huì)跟碰撞體發(fā)生碰撞。

為了使基于質(zhì)點(diǎn)的物理模擬能夠體現(xiàn)毛發(fā)的感覺(jué),HairWorks 為質(zhì)點(diǎn)間增加了一系列的約束,也就是俗稱(chēng)的彈簧。比如圖左中,同一個(gè)頭發(fā)上相鄰質(zhì)點(diǎn)間有長(zhǎng)度約束,太近了會(huì)排斥,太遠(yuǎn)了會(huì)吸引,這有助于保持頭發(fā)的大致長(zhǎng)度。

再比如黃色折線,它表示的是完全受骨骼蒙皮控制的毛發(fā)。它跟紅色這條線,也就是物理模擬控制的毛發(fā)間也有約束,這有助于保持美術(shù)所制作的造型。

另外,HairWorks 還有一個(gè)比較有特色的約束,就是在相鄰的導(dǎo)發(fā)之間也有距離約束,有助于保持毛發(fā)的體積感,一定程度上避免穿插。當(dāng)然還有很多其他種類(lèi)的約束我們就不一一展開(kāi)提了。

為了加速物理模擬,HairWorks 的物理模擬是在 Computer Shader 中并行進(jìn)行的。一個(gè)控制點(diǎn),也就是一個(gè)質(zhì)點(diǎn)對(duì)應(yīng)一個(gè)線程,一個(gè)導(dǎo)發(fā)對(duì)應(yīng)一個(gè)線程組,這就便于使用效率比較高的共享存儲(chǔ)。

但是有些約束是有先后順序依賴(lài)關(guān)系的,例如同一個(gè)質(zhì)點(diǎn)上的兩個(gè)長(zhǎng)度約束,如果調(diào)換執(zhí)行順序,那么執(zhí)行結(jié)果就不一樣了。正確的做法只能是串行解算這些約束,但是串行顯然是不如并行快的。為了加速物理模擬,HairWorks 還是想辦法做到了并行。

如圖,它把長(zhǎng)度約束分為兩組,一組內(nèi)每個(gè)約束都互不相臨。這樣一組的約束就可以并行解算,一組解算完之后,再解算另一組,交替迭代幾次就能獲得比較穩(wěn)定的結(jié)果。

“當(dāng)然后面我們還做了一些物理模擬的拓展和優(yōu)化,例如加入了 3D 風(fēng)場(chǎng)以及允許傳入不穩(wěn)定的物理模擬 TimeStep 等等。”徐行說(shuō)道。

“接下是關(guān)于引擎與跨平臺(tái)的一些分享,這張圖是我們把 HairWorks 集成到自研引擎之后,在《笑傲江湖》和一些 Demo 中的效果。當(dāng)時(shí)另一個(gè)端游項(xiàng)目看到了,覺(jué)得效果不錯(cuò),挺想用。他們是基于 Unity 開(kāi)發(fā)的,所以接下來(lái)我就開(kāi)始了向 Unity 的集成?!毙煨姓f(shuō)。

其實(shí)遠(yuǎn)在完美世界之前,已經(jīng)有很多團(tuán)隊(duì)進(jìn)行了這項(xiàng)工作。比如圖中是 Unity Japan 團(tuán)隊(duì)的成果,但是他們做的集成時(shí)間都比較早了,當(dāng)時(shí)條件有限,所以也存在一些問(wèn)題。比如無(wú)法使用 Unity 內(nèi)部的材質(zhì),或者光照不全,沒(méi)有平行光的投影等等。

他們?yōu)槭裁磿?huì)遇到問(wèn)題呢?這就要講到他們集成的實(shí)現(xiàn)原理。

他們選擇了原生插件這種集成方式,是由于 HairWorks 要用到諸如 Computer、Tessellation 這類(lèi)很底層的圖形功能。所以說(shuō)使用能達(dá)到底層圖形設(shè)備接口,例如 D3D Device 的原生插件機(jī)制還是比較穩(wěn)妥的。

但是也正是因?yàn)樗麄兪鞘褂玫讓訄D形設(shè)備接口,例如 D3D Device,進(jìn)行渲染,而不是使用 Unity 提供的接口例如 DrawRenderer,所以 Unity 內(nèi)的材質(zhì)、燈光、環(huán)境以及渲染管線內(nèi)部的很多信息,都很難傳過(guò)去,也就很難在原生插件里面重現(xiàn) Unity 的渲染效果,所以原生插件渲染出來(lái)的東西往往光照不全。

另外由于 Built-In 管線中提供的插入點(diǎn)有限,所以沒(méi)有辦法渲染陰影深度。上述問(wèn)題如果按原有思路做下去,是很難解決的。但是這些問(wèn)題不解決又沒(méi)有辦法實(shí)際投產(chǎn),所以這些集成最后基本上就被擱置了。

徐行的團(tuán)隊(duì)最初也是一籌莫展的,差點(diǎn)因此放棄,但是最后還是想到了一個(gè)解決方案,那就是既然 Unity 里面的東西很難拿出來(lái),是不是可以不把他們拿出來(lái)放到原生插件里面?而是想辦法把原生插件生成的 HairWorks 的幾何信息傳到 Unity 里面,這樣就可以在 Unity 里做光照了,這樣可行嗎?

徐行的辦法其實(shí)很簡(jiǎn)單,他使用了一種名為渲染代理的方法。所謂的渲染代理其實(shí)就是一個(gè)在 Unity 里面創(chuàng)建的頭發(fā)的包圍體,原生插件把 HairWorks 的幾何信息渲染到了自己創(chuàng)建的 GBuffer 中。

然后渲染代理掛上了 Unity 內(nèi)的材質(zhì),直接參與 Unity 的渲染。與普通材質(zhì)有所不同的僅僅是在渲染的時(shí)候會(huì)讀取我的 GBuffer 中的幾何信息,并把它偽裝成自己的進(jìn)行光照。這樣的話(huà),就可以直接利用 Unity 自帶的渲染機(jī)制,所以渲染出來(lái)的東西跟 Unity 是可以完美融合的。

這個(gè)機(jī)制還有另外的幾個(gè)好處,第一是對(duì)項(xiàng)目的渲染管線沒(méi)有影響,可以直接使用 Unity 材質(zhì),也支持 Shader Graph。所以不管對(duì)美術(shù)用戶(hù)還是技術(shù)用戶(hù)都比較友好。

另外,Unity 很多時(shí)候需要把一個(gè)物體渲染多次,而使用渲染代理的話(huà),就可以避免多次提交復(fù)雜的毛發(fā)幾何體去渲染了。因?yàn)槲颐看翁峤坏?,都只是一個(gè)很簡(jiǎn)單的包圍體。

最后一個(gè)優(yōu)勢(shì),大家可以看出來(lái)這個(gè)機(jī)制很類(lèi)似于延遲渲染,每個(gè)像素上只需要進(jìn)行一次著色,所以是比較高效的。渲染可以使用代理,投影也可以使用代理,如此一來(lái)集成就變得很簡(jiǎn)單了,就不存在之前所說(shuō)的諸多問(wèn)題了。當(dāng)然,后來(lái)有了 SRP,就可以在渲影子的時(shí)候直接調(diào)用原生插件渲染了,不再需要投影代理了。

接下來(lái)就是跨平臺(tái),其實(shí)剛剛不管是 Unity Japan,還是集成,一直是通過(guò)原生插件對(duì)接 Nvidia HairWorks SDK 做的。在 SRP 誕生之前,這可能是唯一能夠跑通的方法。HairWorks SDK 預(yù)留了跨平臺(tái)的設(shè)計(jì),但是 Nvidia 只實(shí)現(xiàn)的 DX11 和 DX12 的版本,剩下所有的圖形接口都需要去重新實(shí)現(xiàn)一份 HairWorks SDK 的底層,這個(gè)工程量是比較大的。而且由于很底層,所以難度也比較高。徐行團(tuán)隊(duì)花幾個(gè)月的時(shí)間才實(shí)現(xiàn)了一次 PS4 平臺(tái),雖然是做完了,但是做完之后覺(jué)得不能再用這種方式繼續(xù)往下做了。

得益于近些年 Unity 的進(jìn)化,特別是 SRP 的加入,讓直接在 Unity 內(nèi)實(shí)現(xiàn)這種復(fù)雜功能變成了可能。我利用近期 Unity 提供的一些新功能,例如 Computer Shader、CommandBuffer、RenderFeature、CustomPass 等等,直接把紅框內(nèi)的整個(gè)流程包括資源加載、約束初始化、物理模擬、幾何體渲染,這些全部都在 Unity 內(nèi)部重新實(shí)現(xiàn)了一遍。

這個(gè)流程比之前的 PS4 移植要順利得多,因?yàn)楝F(xiàn)在 Unity 的渲染開(kāi)發(fā)是很高效的,做任何修改都不需要關(guān)編輯器,也不需要花很長(zhǎng)的時(shí)間來(lái)編譯,可以即時(shí)看到效果。

另外由于有像 CustomPass 和 RenderFeature 這樣方便的機(jī)制,對(duì) SRP 的源碼修改其實(shí)只有幾行。

接下來(lái)講一下毛發(fā)著色,我們可以先看一下最終的效果。

說(shuō)到毛發(fā)著色,我們首先會(huì)想到的就是 Kajiya-Kay 模型,它用毛發(fā)的切線替代了常用的法線,把 cos 換成了 sin,快速實(shí)現(xiàn)了類(lèi)似于頭發(fā)的效果。

但是如圖所示,雖然它產(chǎn)生了類(lèi)似于頭發(fā)的高光,但是塑料感很強(qiáng)。在 2003 年 Marschner 提出了一種更接近物理真實(shí)的毛發(fā)著色模型,中間就是 Marschner 成果,右邊是真人照片。在不考慮造型的情況下,可以說(shuō)效果已經(jīng)很接近真實(shí)的照片了。

它首先是對(duì)與毛發(fā)產(chǎn)生的交互光線進(jìn)行分類(lèi),打在毛發(fā)表面就被反射的光線被稱(chēng)為 R。打入頭發(fā),然后又從頭發(fā)背面射出的光線被稱(chēng)為 TT。打入頭發(fā),在頭發(fā)內(nèi)部被反射,又從頭發(fā)正面透出來(lái)的光線被稱(chēng)為 TRT,這里面 R 和 T 分別代表反射和透射。

光線在頭發(fā)內(nèi)部行進(jìn)的過(guò)程中,他的部分能量會(huì)被頭發(fā)的內(nèi)核吸收,所以說(shuō)圖中的 TT 和 TRT 都會(huì)帶有頭發(fā)的顏色,而R就類(lèi)似于一般的高光,不受頭發(fā)顏色的影響。

另外,由于頭發(fā)表面的鱗片與毛發(fā)切線形成了一定的角度,這導(dǎo)致出射的 R 和 TRT 的角度產(chǎn)生了一定的偏差。直觀地來(lái)說(shuō),就是他們兩個(gè)的中心是分離的。

如中間的部分所示,白色的高光是 R,最上面呈現(xiàn)發(fā)色的高光就是 TRT,可以看出他們的中心是有一定偏差的。

Marschner 的另一項(xiàng)重要貢獻(xiàn),就是將散射光線在毛發(fā)橫截面和縱截面的能量分布分開(kāi)建模,這極大的簡(jiǎn)化了建模的難度,減少了單個(gè)分布函數(shù)的參數(shù)。

盡管如此,這個(gè)模型的數(shù)學(xué)計(jì)算還是十分復(fù)雜的。在 Shader 實(shí)現(xiàn)一套比較麻煩,性能也比較低。

為了提高計(jì)算性能,英偉達(dá)很早就提出了一種簡(jiǎn)便的方法,就是把橫截面和縱截面出射光的能量分布烘培到兩張紋理里面,渲染的時(shí)候查詢(xún)即可。這種方法又被稱(chēng)之為查找表法。圖中就是英偉達(dá)用這種技術(shù)制作的美人魚(yú) Demo。

但是這個(gè)方法有一個(gè)的問(wèn)題,就是只支持一種頭發(fā)顏色和一種粗糙度。

受到英偉達(dá)思路的啟發(fā),徐行寫(xiě)了一個(gè)很簡(jiǎn)單的光追小程序,從各個(gè)方向向毛發(fā)發(fā)射光線,再在各個(gè)方向統(tǒng)計(jì)出射光線的能量分布,最后把能量分布存入紋理中。

但是在這個(gè)思路的基礎(chǔ)上,他又做了兩個(gè)擴(kuò)展。第一是徐行希望美術(shù)能夠調(diào)節(jié)粗糙度,所以他將 32 個(gè)不同粗糙度的能量分布都烘焙了,排成了一個(gè)序列。

第二是在能量分布圖中,沒(méi)有包含毛發(fā)中心對(duì)光線吸收,而是用了一組新的紋理來(lái)記錄光線在毛發(fā)中行進(jìn)的平均距離。根據(jù)這個(gè)距離和美術(shù)設(shè)定的毛發(fā)顏色換算得到的吸收率,就可以對(duì)毛發(fā)光線能量進(jìn)行衰減,從而體現(xiàn)不同的毛發(fā)顏色。

最終的效果如圖,大家可以從圖左中觀察到 R 和 TRT,可以在圖右中觀察到明顯的 TT。

主站蜘蛛池模板: 成人免费乱码大片a毛片| 亚洲日本久久一区二区va | 天堂8在线天堂bt| 啊用力太猛了啊好深视频| 久久精品99久久香蕉国产| 亚洲国产成人精品激情| 欧美黄色一级在线| 月夜直播在线看片www| 在线免费观看污网站| 伊人久久大香线蕉亚洲五月天| 中文字幕av无码无卡免费| 野花香高清在线观看视频播放免费| 欧美午夜性春猛交| 国产精品美女视频| 亚洲欧美日韩高清综合678| 99精品视频在线观看免费| 男男暴菊gay无套网站| 巨大一下一寸挤进校花| 免费观看一级毛片| 中国speakingathome宾馆学生| 羞羞网站在线观看| 扒开双腿疯狂进出爽爽动态图| 国产丰满岳乱妇在线观看| 久久国产精品电影| 邱淑芬一家交换| 无码专区天天躁天天躁在线| 四虎影视久久久免费观看| 东方美女大战黑人mp4| 欧美综合自拍亚洲综合图片区| 国产成人在线网址| 久久婷婷国产综合精品| 竹菊影视欧美日韩一区二区三区四区五区 | 亚洲一级毛片在线播放| 亚洲精品一二区| 成年福利片120秒体验区| 农村乱人伦一区二区| www.av毛片| 毛片基地在线观看| 国产精品久久久久久久伊一| 九九视频在线观看视频23| 高清在线精品一区二区|