国产av一二三区|日本不卡动作网站|黄色天天久久影片|99草成人免费在线视频|AV三级片成人电影在线|成年人aV不卡免费播放|日韩无码成人一级片视频|人人看人人玩开心色AV|人妻系列在线观看|亚洲av无码一区二区三区在线播放

網(wǎng)易首頁 > 網(wǎng)易號 > 正文 申請入駐

《戀與深空》引擎工程師的一次純技術分享

0
分享至

在今天舉行 的 第十屆Unite開發(fā)者大會,《戀與深空》的引擎工程師們首次對游戲進行深度技術分享,這是疊紙非常少有的在公開場合的內(nèi)容分享,現(xiàn)場可以說是座無虛席。

會議結(jié)束后,疊紙官方也將今天現(xiàn)場的內(nèi)容發(fā)到了官方公眾號【疊紙游戲招聘】中,我們將本文完整的轉(zhuǎn)發(fā)出來,希望有更多的行業(yè)精英可以看到這次的技術“干貨”。

以下為《戀與深空》技術分享完整內(nèi)容回顧:


《戀與深空》渲染底層框架的分享內(nèi)容主要涵蓋【場景渲染優(yōu)化、光照方案與管線設計、陰影優(yōu)化】三部分。在開發(fā)過程中,我們基于Unity 2019對引擎源碼進行深度修改,開發(fā)了一套自定義的SRP管線。目前Android線上版本為GLES 3.1,未來也將上線Vulkan版本,持續(xù)提升性能,滿足玩家對高品質(zhì)游戲的需求。

1. 場景渲染優(yōu)化

在場景渲染優(yōu)化中,我們開發(fā)了一套名【RendererGroupRenderer】的場景渲染系統(tǒng),將每個渲染批次稱之為一個RenderGroup。通過這套系統(tǒng)我們實現(xiàn)了以下功能:

  • 自定義靜態(tài)場景描述:我們?nèi)コ鼼ameObject,避免了更新大量GameObject時帶來的性能損耗。

  • 優(yōu)化CPU→GPU Upload 頻率:主要包括InstanceData和ConstantBuffer的Upload。關于InstanceData的Upload優(yōu)化,我們在項目初期針對室內(nèi)小規(guī)模場景,采用的是靜態(tài)生成InstanceDataBuffer,配合BVH分割裁剪的形式。隨著項目推進,場景精度要求不斷提高,后期便轉(zhuǎn)向在GPU端完成裁剪與instance填充。ConstantBuffer的Upload優(yōu)化將在后面【單DrawCall性能優(yōu)化】部分進行詳細說明。

  • CPU側(cè)Burst+Job System并行粗裁剪:對靜態(tài)物件我們通過Burst+Job System實現(xiàn)了一套高度并發(fā)的裁剪系統(tǒng),同時只在CPU側(cè)進行粗略的裁剪,將細粒度的裁剪任務交由GPU完成。

InstanceData數(shù)據(jù)形式

業(yè)界常用Constant Buffer形式的InstanceData存在一些缺點,比如64KB 尺寸限制、常量緩存小、動態(tài)索引時容易發(fā)生緩存擊穿導致性能下降等。另一種常用形式是用SSBO來傳遞InstanceData,但這種方法讀取性能通常不如緩存未擊穿情況下的ConstantBuffer,并且部分安卓設備在GLES下不支持在vertex shader中讀取SSBO,這也限制了它的兼容性。同時這兩個方案都有共同的問題:依賴動態(tài)索引,對低端手機性能不友好。

針對以上問題,我們提出了一種“新瓶裝舊酒”的方案——Vertex Stream based Instance Data。

  • 使用PerInstance Step的Vertex Stream作為Instance Buffer;

  • 走Vertex Fetch緩存,無需動態(tài)索引,Cache命中率高,無兼容性問題;

  • 通過ComputeShader向Instance VertexBuffer輸出,實現(xiàn)GPU Driven。

使用PerInstance Step的Vertex Stream作為Instance Buffer——這是一種在GPU Instancing誕生之初就被支持的Instance方法,既可以避免動態(tài)索引帶來的性能問題,也避免了SSBO的兼容性問題。我們還可以通過ComputeShader向Instance VertexBuffer輸出來實現(xiàn)GLES下兼容性較高的GPU Driven。

最后,由于Unity引擎在底層沒有支持PerInstance Step的Vertex Stream,我們對引擎也做了相應的定制,最終暴露給上層的是CommandBuffer中添加的一個DrawMeshInstancedTraditional接口,它需要將另一個mesh作為instance data傳進來。我們也加了相應的接口來配置instance mesh中各個數(shù)據(jù)段對應的頂點semantic。

GPU Driven

我們會依據(jù)Group數(shù)量與Instance數(shù)量,提前分配IndirectParameter Buffer與Instance Data Buffer(這里Instance Data Buffer只是提前分配了空間,實際的數(shù)據(jù)為GPU Cull時填入)。

同時,我們會預計算每個Group的Instance Offset,并將其存儲到Parameter的InstanceStart項,全程只綁定一份Instance Buffer。


此外,我們還需要生成逐物件信息Buffe(包含GroupID、LOD Distance Range、Bounds、Transform等信息),用于在GPU裁剪時獲取每個物件的屬性。

  • CPU剪裁:在GPU裁剪之前,我們會先執(zhí)行一次CPU粗裁剪,以判斷Group整體是否可見。從一個根包圍盒開始,比較物件包圍盒體積總和與合并后包圍盒的體積比值,低于閾值就遞歸分裂包圍盒(主要目的為避免兩個物件距離過遠,拉出一個超大總包圍盒的情況發(fā)生)。同時結(jié)合PVS進一步判斷Group的可見性,因為我們沒有類似DX12的IndirectExecute,我們的GPU裁剪只能減少instance數(shù),并不能消除Group整體的drawcall,因此需要,通過CPU裁剪盡可能準確地剔除掉完全不可見的Group。

  • GPU剪裁:GPU裁剪則通過一次dispatch對所有Group進行逐物件3段裁剪,包含視錐裁剪、LOD裁剪、Hiz遮擋剔除,通過裁剪將Parameter的Instance Count加1,并輸出InstanceData。

  • 陰影剔除:我們參考了龍之教條分享的方法,將畫面深度重投影到陰影空間作為Shadow Reveiver Mask,若Shadow Caster投出的Volume與Mask不相交,就可剔除避免多余陰影渲染。

此外關于我們“為什么沒有實現(xiàn)Cluster/Meshlet”部分,首先它在移動端存在較大基礎開銷,其次在GLES下實現(xiàn)Cluster也存在兼容性問題。綜合考慮下,我們認為優(yōu)先優(yōu)化單DrawCall的性能更能為我們帶來免費且直接的性能提升。

單DrawCall性能優(yōu)化

在過往的觀察中,我們發(fā)現(xiàn)許多對于渲染的CPU耗時優(yōu)化往往過于關注DrawCall數(shù)量,而忽視了每個DrawCall本身的耗時。我們認為降低DrawCall數(shù)量只是一種優(yōu)化方法,最終的CPU耗時才是唯一的衡量指標。

現(xiàn)代移動設備與圖形標準其實早就可以勝任大量drawcall,這部分在HypeHype引擎團隊在Siggraph 2023中也有過分享——他們在iphone 6s上測試了一萬個不同Mesh與材質(zhì)的DrawCall,耗時僅有11.27ms。其他同等的安卓設備也都基本能維持在60幀以上。而在2014年Metal剛剛誕生時,也提出過比GLES多畫10倍DrawCall的口號。

11年后的今天,我們?nèi)詾镈rawCall過多而苦惱的原因,主要來自多方面的開銷,包括PSO切換過多、Buffer提交與拷貝、引擎渲染邏輯以及過多RHI接口調(diào)用,都會增加CPU負擔。因此我們認為性能優(yōu)化不能只盯著DrawCall數(shù)量,而要綜合考量這些因素。

  • PSO切換優(yōu)化:主要取決于每個項目對shader變體數(shù)量和shader復雜度的權衡。RenderGroup渲染隊列會根據(jù)shader,material,mesh的優(yōu)先級排序,同時我們對陰影進行特殊處理:無AlphaTest的材質(zhì)統(tǒng)一用相同shader渲染Shadow Depth,減少陰影渲染時的PSO切換頻率。

  • Buffer提交優(yōu)化:在GLES下,Map/Unmap buffer會帶來顯著開銷,現(xiàn)代RHI支持的persistent map雖能顯著減少upload耗時,但仍無法避免數(shù)據(jù)從主線程到渲染線程,再到buffer內(nèi)存的多次拷貝以及memcmp。因此我們采用了以下三種針對性的策略,顯著減少了Buffer Upload:

    • PerRendererBuffer將逐Renderer的參數(shù)(如物體所受的環(huán)境光SH),存放在由Renderer對象維護的Uniform Buffer中,渲染時直接綁定;

    • PerShaderBuffer針對不需要逐材質(zhì)變化的uniform buffer,只在shader切換時提交一次,相比PerRendererBuffer來說,PerShaderBuffer更加靈活,可以支持不同的shader變體;

    • 針對PerMaterialBuffer,我們借用了SRP Batcher代碼預生成逐材質(zhì)buffer并直接綁定。

  • 渲染邏輯優(yōu)化:商業(yè)游戲引擎為保證靈活性與穩(wěn)定性,渲染時會進行復雜的邏輯判斷。比如在Unity引擎內(nèi)部,每次調(diào)用Draw時會先調(diào)用一個ApplyMaterial函數(shù),它會在渲染之前更新所有的渲染狀態(tài)與參數(shù),當DrawCall數(shù)量較多時存在可觀的耗時。因此我們進行了以下優(yōu)化:

    • 對ApplyMaterial接口進行了單獨拆分,僅在材質(zhì)或參數(shù)需要切換時才由上層主動調(diào)用;

    • 只需改變PerMaterialBuffer時,改用簡化后的專用接口。

優(yōu)化后,我們的CPU在在相同DrawCall下耗時減少1/3。

  • RHI調(diào)用優(yōu)化:RHI調(diào)用優(yōu)化主要的目標是減少除了Draw Primitive以外的其他圖形API調(diào)用,具體優(yōu)化包括:

    • 合并相同stride的Vertex&Index Buffer,避免逐Draw Call bind VB/IB,耗時減少15%;

    • Resource未發(fā)生變化時,跳過DescriptorSet設置,耗時進一步減少30%;SetDescriptors本身耗時較高時候,而且切換Descriptor還會增加下一次draw的耗時,這個在Arm的Best Practice Guide里有過介紹。

我們在低端安卓設備上測試了5000個DrawCall的耗時。使用引擎原生的渲染時,渲染線程的耗時是34.79ms。當我們對Buffer提交與渲染邏輯進行優(yōu)化后,耗時降低到22.97ms。在進一步優(yōu)化RHI調(diào)用次數(shù)后,耗時進一步大幅降至了11.8ms。最終我們在DrawCall數(shù)量不變的前提下,讓CPU耗時減少到了原來的1/3以下。


其他優(yōu)化嘗試Benchmark場景測試結(jié)果

我們還嘗試了一些新的RHI特性,包括:

  • Multi-Draw Indirect(MDI):在支持的設備上能夠帶來明顯優(yōu)化,一定程度上改善GPU遮擋剔除可能會提交空DrawCall的問題(CPU端提交減少);

  • Bindless:然而,Bindless的表現(xiàn)卻不盡如人意,即便在最新的安卓設備上也出現(xiàn)了神秘的負優(yōu)化。結(jié)合MDI與Bindless,我們可以實現(xiàn)幾乎用一個DrawCall渲染所有物件,但是CPU耗時卻比不合批時還更高。這也是一個過度關注DrawCall數(shù)量的反面案例。當然,我們期待以后的移動芯片對bindless能有更好的支持?,F(xiàn)階段的話,我們嘗試基于Unity Texture Streaming擴展出了一套無Feedback SVT系統(tǒng)作為替代方案,這個方案也還在驗證階段。

從Benchmark場景測試結(jié)果來看,RenderGroupRenderer對比原始無instancing渲染,DrawCall減少了1/3,渲染線程耗時大幅減少3/4,主線程耗時也減少了2/3(雖然C,但引擎原生裁剪與GameObject更新耗時減少,整體仍然帶來了大幅的優(yōu)化)。

2. 光照方案

光照方案

  • 前向渲染管線:

我們在項目中選擇使用前向渲染管線,包含以下多方面考慮:首先,前向管線在應對美術復雜且多變的需求方面有其優(yōu)勢,我們不需要擔心一些材質(zhì)屬性的添加是否會導致GBuffer膨脹。

其次,傳統(tǒng)的延遲管線對于移動平臺而言帶寬不太友好。OnePassDeferred則在靈活性方面存在一些局限,比如無法在RenderPass中間改變RT的尺寸,也不能fetch當前位置以外的像素內(nèi)容。

在GLES下,F(xiàn)rameBufferFetch的兼容性也存在問題,不同芯片支持的fetch RT數(shù)量不同,有的只支持1張RT,需要改成通過PLS實現(xiàn),但是我們測試PLS的性能并不理想。

另外,引擎自帶的逐物件4盞光源對于較大的物件來說不太夠用,因此我們嘗試了Forward+。但是Forward+在早期設備上耗時太高,若限制逐tile最大光源數(shù),鏡頭變化時,tile內(nèi)光源數(shù)量不可控,超上限會帶來表現(xiàn)bug。

為解決這些問題,我們采用了水平世界空間Tile劃分——默認2米一格,分布于相機前方,逐Tile最多4盞光源,128*128 Index Map。這種劃分方式使Tile光源重疊狀態(tài)穩(wěn)定,便于在制作時及時發(fā)現(xiàn)超限問題。


  • Vulkan版本管線改進

我們在未來的Vulkan版本的管線中增加了基于Subpass的Light Pre-Pass。

在Pre-Z Pass中,我們會輸出一張簡易的GBuffer RT并且store下來。由于我們的local light光照使用了無fresnel的簡化PBR模型,所以我們不需要在GBuffer中輸出specular或者Albedo,只將normal,roughness和一些特殊的材質(zhì)id或?qū)傩孕畔ack到一張RGBA8的Gbuffer上,然后就可以跑一遍類似Deferred Shading的光源Volume渲染流程,將幾何光照結(jié)果保存到Tile Memory上。

之后在Shading Pass中,我們會把物件再畫一遍并fetch這些光照信息,再結(jié)合渲染時獲得的albedo等材質(zhì)屬性,得到最終的光照結(jié)果。

我們將TAA所需的MotionVector Encode為RGBA8,R + G == 0代表無有效速度,這樣某些不輸出速度的材質(zhì)可在BA通道存其他信息。

比如我們針對一些簡易且大量的植被,會在MotionVector的BA通道上保存他們的UV信息,這樣在Shading Pass時,我們只需要后處理獲取gbuffer中的幾何信息與MotionVector中的UV信息,即可還原出植被的材質(zhì)表現(xiàn)。

Vulkan版本的管線流程大致如下:首先由PreZ Pass輸出Depth,GBuffer與MotionVector,然后計算陰影的遮擋剔除,接著執(zhí)行陰影的深度渲染,再然后是一些AO和屏幕空間SSS之類的計算然后我們就進入NativeRenderPass,在SubPass中計算ShadowMask,Light Pre-Pass,以及執(zhí)行正常的Shading Pass。最后退出RenderPass,再執(zhí)行其他后處理Pass。


Vulkan版本管線改進也存在一定局限,比如Light Pre-Pass只能替換默認Lighting Model,對于需要更多Gbuffer通道的Lighting Model,還是需要采用Forward+。

不過我們提供了一個逐光源可選參數(shù),可以針對某個光源強行使用Standard Lit Model,對所有材質(zhì)統(tǒng)一處理,這樣可以在犧牲Lighting Model準確性的條件下實現(xiàn)讓同Tile內(nèi)的像素受4盞以上燈的影響。

  • GI

Diffuse GI部分,我們采用了較為傳統(tǒng)的Lightmap+Light Probe的方式,Lightmap只保存間接光信息,Light Probe除了正常的逐物件單個采樣點的模式以外,我們還提供了一種多采樣點模式,能為每個物體設置多個采樣點,依據(jù)線段、三角形或四面體的重心坐標進行插值。

在以下兩張對比圖中,左圖為單采樣點的效果,box的底部為統(tǒng)一的環(huán)境光照;右圖則為使用兩個采樣點的結(jié)果,可以發(fā)現(xiàn)左右兩邊受到了不同的間接光照。


Specular GI方面,我們主要是基于使用了AABB校正的Reflection Probe。另外對于一些特定的地板或水面,我們還會使用平面反射代理。大致可以看成一種專門用來畫反射的HLOD。

此外我們還參考了戰(zhàn)神的做法,對Reflection Probe的CubeMap做了歸一化。具體來說就是根據(jù)CubeMap的像素生成一份環(huán)境光照的SH系數(shù),將CubeMap中的像素顏色與該方向的環(huán)境光照相除,得到歸一化的CubeMap。在實際渲染時,再用每個像素在反射方向上所受的實際環(huán)境光照與CubeMap像素相乘,還原出反射顏色。

這種做法的好處是,即使大量物件采樣同一個Reflection Probe,不同區(qū)域的反射也能產(chǎn)生不同的明暗差別。

3. 陰影優(yōu)化

功能設計

我們陰影系統(tǒng)的基本設計為:

  • 三級CSM+角色特寫陰影/多角色POSM:3級Cascade的CSM+1級角色專屬的特寫陰影,在某些多角色場景時會使用POSM(Per-Object Shadow Map);

  • 可支持兩盞錐燈投影;

  • ScreenSpaceShadowMask:將以上陰影的結(jié)果都將輸出到了一張RGBA8的ScreenSpaceShadowMask上;

  • R:Directional Shadow, G: Local Shadow 1, B: Local Shadow 2, A: AO:R通道保存主光陰影,G和B保存了錐燈陰影,A通道保存了AO信息。

距離剔除

我們首先做了一個簡單的距離剔除,根據(jù)陰影距離修改ScreenSpaceShadow后處理三角形頂點的深度值,之后再用ZTest Greater渲染,剔除陰影距離外的Shadow計算。

因為在計算陰影時要采樣depth,我們需要兩份depth分別用于Test與Sample,我們會在NativeRenderPass中拷貝一份Memoryless的Depth Buffer用于Test,盡量避免額外的讀寫帶寬。

半影區(qū)域檢測

我們增加了半影區(qū)域檢測功能,先在1/4分辨率下計算一次PCF,隨后在全分辨率Shadow Pass里采樣1/4 mask,僅對shadow值處于中間區(qū)域的像素執(zhí)行全分辨率PCF,在保證效果的同時降低計算量。

為了避免這樣做之后存在某些細節(jié)像素檢測不準確的問題,我們會分別依據(jù)1/4 Buffer中Position的偏導與全分辨率Gather的4個深度值計算兩組法線。若法線夾角大于閾值,則判定低分辨率像素不可靠,強行執(zhí)行全分辨率PCF。

以下為場景的Debug視圖,紅色區(qū)域被我們判定為半影區(qū)間,只有這些像素才會執(zhí)行全分辨率的PCF。


逐像素bias

我們利用Receiver Plane Depth Bias算法實現(xiàn)了逐像素的Shadow Bias。它的原理也比較簡單,首先對屏幕空間shadow coordinates偏導應用二維鏈式法則,求出陰影空間偏導。


利用偏導與PCF采樣偏移我們可以求出bias值。對于中心點來說,我們增加了1個像素偏移的bias結(jié)果作為起始bias。

下圖為固定bias與逐像素bias的對比結(jié)果:


左圖使用固定bias值,可以看到box的底部有一段漏光區(qū)域,并且與光照方向接近垂直的表面存在部分自陰影走樣;使用逐像素bias之后(右圖),我們只會在偏導較大的區(qū)域增加bias,可以在保持細節(jié)投影的同時解決自陰影的走樣問題。

不過,當屏幕深度不連續(xù)時,逐像素bias可能算出錯誤結(jié)果,導致一些漏光現(xiàn)象。為了解決這一問題,需要美術手動指定bias的最大最小范圍。

Scrolling Cached Shadow Map

針對DrawCall較多的場景,我們還嘗試了Scrolling Cached Shadow Map,具體包括:

  • 緩存CSM深度,對于前后兩幀都被陰影視錐完全包含的對象,將上一幀的CSM滾動到當前幀投影位置直接得到陰影深度,避免直接渲染對象;

  • 只對最后一級cascade應用Scrolling,當cascade范圍比較小時,大量物體與會與視錐相交,優(yōu)化效果就會受限;

  • 間隔多幀更新緩存,減緩帶寬壓力。

在未來,我們還準備支持Local ShadowMap Atlas以及緩存機制。我們將會支持兩盞以上的局部燈投影,并且根據(jù)光源的屏占比動態(tài)調(diào)整ShadowDepth精度了,對于遠距離的局部光源,也會引入靜態(tài)緩存支持。


1. 角色光照方案

在角色光照方案中,相信大家多多少少都會遇到以下幾類問題:


對這些問題進行拆解,則可以總結(jié)為以下3個需求:


基于以上需求,我們進行了具體角色光照方案設計。

光照是由【直接光】和【間接光】組成的,一般情況下我們只會有一個平行光——我們習慣稱之為主光。主光正常照亮場景,但在照亮角色的時候我們保留它的方向,用一個類似后處理盒子的方式覆寫主光的顏色和亮度。具體實現(xiàn)方式為:

  • 給Shader多傳一份角色主光顏色,角色的Shader在獲取主光時獲取到的顏色為角色主光顏色;

  • 給角色提供了一盞額外的不投影的平行光用來做輪廓光;

  • 同時預留了兩個額外光給角色,額外光可以是任意的點光和射燈組合,可以正常照亮范圍內(nèi)的角色和場景物件( 因為一個2米的格子最多四盞額外光,所以將2個燈光劃分給角色)。

間接光我們使用Unity的LightProbe系統(tǒng)來創(chuàng)建探針,自己實現(xiàn)了保存間接光到探針里的部分,把場景的探針和角色的探針分開兩套,分別存儲和使用;

環(huán)境光高光我們使用同一個反射探針,但對于一些特殊的材質(zhì),我們提供了材質(zhì)上輸入CubeMap覆蓋環(huán)境的反射探針的選項。


我們把這些影響角色的光照信息存到一個Scriptableobject里,由燈光師調(diào)整好之后保存為一個模板;下方右圖為角色燈光方案保存的信息,包含了上面提到的兩盞平行光,兩個額外光,還有探針保存下來的sh,以及一些后處理盒子上可以額外調(diào)整的信息和是否使用自定義的反射探針。

最后用一個manager使用類似棧的方式去管理,這里選用棧的管理方式跟具體使用強相關——通常情況下除了加載新的燈光方案之外,最常用的一個功能就是還原上一個燈光方案效果,因此我們采用了棧的管理方式。


到這里,這個方案已經(jīng)具備了角色/場景分開、可實時切換、支持定制保持模板這些功能。最后我們把切換燈光方案定義成劇情編輯器上的一個事件行為,支持了可銜接光照動畫。

可銜接光效果如下所示:


下圖為項目專用劇情編輯工具,基本上所有的燈光和陰影相關的參數(shù)及部分后處理、物理效果都可以在這個劇情編輯器控制。


2. 特寫陰影

光和影一直都是密不可分的。如前文所提到,我們的陰影方案為三級CSM加特寫陰影,實現(xiàn)原理就使用角色身上的一根可指定的骨骼做球心,構成一個指定半徑的球,用這個球來構建和生成這張陰影圖,在屏幕空間陰影的時候會進行精度比較,使用這張陰影圖和級聯(lián)陰影中精度較高的一張作為這個像素的Shadow Map。


通過以下動圖可以看到,角色原本整個都在主光陰影里,打開特寫陰影的時候變成了可以被主光正常照亮,就是因為特寫陰影修改了近裁切平面;也就是說我們的特寫陰影是一張單獨可調(diào)參數(shù)的陰影圖,具體參數(shù)包括遠近裁切平面,最遠距離,還有使用哪一盞光和往往最讓人頭疼的bias。


3. 皮膚細節(jié)

皮膚上我們聚焦一些細節(jié)表現(xiàn),具體以臉紅效果和流汗效果為例。

  • 臉紅效果

通常來講,臉紅的過程是一個逐漸變化并且不同區(qū)域變紅程度不一樣的過程,比如大部分人在臉紅的時候會先從耳朵開始紅,然后是臉頰,偶爾會有整張臉變紅的表現(xiàn)。


為了模擬這個過程,我們采取了以下方式,使畫面更加生動和真實:

    • 手繪遮罩:基于遮罩紋理控制臉紅區(qū)域、顏色梯度與強度;

    • 多通道獨立:可分別調(diào)節(jié)面部、耳朵、鼻子等不同區(qū)域的紅暈效果;

    • 預存變化過程:臉紅的過渡過程分通道記錄在對應曲線上,實現(xiàn)自然的情緒表達。

  • 流汗效果

我們游戲里提供了運動陪伴功能,男主會進行一些運動訓練的陪伴,因此也就需要提供相應的流汗效果。具體實現(xiàn)主要通過以下三個方面:

  • 材質(zhì)與粒子結(jié)合:材質(zhì)著色器模擬皮膚表面光澤與濕潤度,汗珠效果提供附著在皮膚上的材質(zhì)實現(xiàn)和vfx實現(xiàn)可供選擇;

  • 遮罩控制流汗區(qū)域:使用遮罩圖確定材質(zhì)流汗區(qū)域,增強流汗效果的真實性和藝術性;

  • 數(shù)據(jù)自動化傳遞:主控參數(shù)變化自動驅(qū)動材質(zhì)與粒子參數(shù)。

下圖為一些具體的計算方式與最終效果示意。


△計算汗滴生成位置并修改汗滴位置粗糙度


△通過uv格子id生成隨機數(shù)


△模擬汗滴下落的軌跡


△運動陪伴系統(tǒng)流汗效果


物理效果的分享主要圍繞四個方面,包括布料模擬實現(xiàn)、實時表演控制、基于Unity DOTS的開發(fā)、碰撞檢測模塊。

1. 布料模擬實現(xiàn)

為了解決項目中的一些針對性的問題,我們內(nèi)部自研了一套布料模擬的系統(tǒng)。

基于骨骼的布料模擬系統(tǒng):StrayCloth

StrayCloth采用XPBD結(jié)合sub step的模擬方式。相比PBD,XPBD的優(yōu)點是擺脫了迭代次數(shù)和時間步長的依賴,結(jié)合Substep可以顯著提升解算的收斂效果。

比較特殊的地方在于,我們使用骨骼作為模擬粒子,也就說每個粒子除了位置以外還帶旋轉(zhuǎn)信息。

在具體的substep實現(xiàn)中,我們針對不同性能壓力場景采用動態(tài)的子步幅時間,在1/200 -1/300之間。并且對場景中的運動對象進行運行插值,這樣碰撞的效果會更加穩(wěn)定。事實上運動插值雖然性能開銷不是很高,但是由于類型眾多,比如有靜態(tài)粒子,碰撞體,風場等,實踐起來還是非常麻煩的。


為什么使用骨骼而不是代理網(wǎng)格?主要出于以下三個原因:

  • 戀與深空在劇情、戰(zhàn)斗、換裝中的表現(xiàn)需求復雜,骨骼方案可以很好的過渡動畫和解算;

  • 在可控性需求和移動端性能限制下,骨骼方案給美術的自由調(diào)節(jié)空間更大;

  • 使用骨骼+約束可以構建類似Mesh的結(jié)構來達到相近的效果。

骨骼約束方案

在已有的骨骼布料方案里,骨骼約束實現(xiàn)常采用基于Local和Global形狀約束的實現(xiàn)方式,雖然簡單快速,但是也有明顯的缺點——在用來做布料模擬時,效果偏向卡通風格,不符合《戀與深空》追求的3D寫實風格;而且它的參數(shù)調(diào)整不直觀,因為它有gloabl和local兩個彎曲強度參數(shù),不利于美術調(diào)整以及在不同場景下的效果匹配。


因此,我們在骨骼約束方案上,選擇了基于Cosserat Rod的骨骼約束。它的優(yōu)點包括:

  • 效果上更加自然,貼近戀與深空整體的寫實美術表現(xiàn)風格

  • 參數(shù)調(diào)整上更加直觀,并且三個軸向強度分離,在一些場合比如模擬裙子的時候,可以通過各向異性的彎曲強度來近似裙撐的效果。

  • 頭發(fā)模擬中可以直接復用,所以我們頭發(fā)和衣服也可以共用一套約束。

具體效果可以參考最新日卡的表現(xiàn):


布料與角色連接

布料和角色的連接主要通過兩種方式:

  • 層級:靜態(tài)骨骼直接受角色的骨骼動畫影響,根據(jù)層級關系進行移動。

    這種方式比較簡單,在一些偏向于剛性的連接部位時表現(xiàn)良好。但是對于一些骨骼交界有多個骨骼影響或者存在一定幅度拉伸和收縮的較為復雜的位置,例如手肘、肩部、腰部,表現(xiàn)上容易出現(xiàn)布料和角色分離。

  • 吸附:靜態(tài)粒子受角色模型的錨定三角形控制。并行bake mesh,通過重心坐標每幀計算更新。

對于三角形存在的退化的特殊情況,我們使用三角形頂點的蒙皮骨骼的變換,進行加權平權來更新靜態(tài)粒子的transform。


碰撞方案

碰撞方案上,我們使用一個dynamic Bvh來作為場景碰撞的broad phase管理,每個角色作為sub tree包含其內(nèi)部的碰撞體作為sub tree node。

同時,我們通過角色id,分享可見性還有部件類型,這個三個規(guī)則來實現(xiàn)不同角色、不同部件的碰撞規(guī)則的共享規(guī)則管理。

在narrow phase 當中,我們不直接生成contact,而是緩存碰撞體對,在substep中再具體的解決,因為我們采用的sub step的優(yōu)點,大多數(shù)情況下直接使用DCD就可以避免一些快速運動下造成的穿透問題,不需要引入ccd或者predictive contact等一些操作。


  • Mesh Collider實現(xiàn)

對于參數(shù)化的幾何碰撞體,例如plane、capsule、box,可以比較簡單的解決它們和粒子以及edge的碰撞。在肩頸和胸背部等復雜部位,參數(shù)化的幾何體難以準確的表達角色模型形態(tài),表現(xiàn)上容易發(fā)生穿透,所以在這些部位我們大量的使用Mesh collider。

但是mesh collider作為不規(guī)則的凹體,有時也可能是非閉合的,想達到精準的碰撞效果相對參數(shù)化幾何體就比較困難,特別是在移動設備下,因此我們采用散列哈希來作為三角形的粗略查找方式,結(jié)合緩存的鄰近三角形結(jié)果,在迭代開始前生成一次粒子-三角形碰撞對,后續(xù)的迭代中判讀粒子是否在三角形的范圍,如果超出三角形的范圍,通過模型的三角形鄰接關系進行限制步幅的三角形查找,來獲取最近的三角形,并且緩存結(jié)果作為下一次使用。

下方的動圖是項目中的一些具體表現(xiàn)示例,可以看到表現(xiàn)上是比較穩(wěn)定的。


Face Collider

面部碰撞體可以看作是特殊的Mesh collider,相對于基本的mesh collider,它形態(tài)較為固定,也較為平滑,從模型中心出發(fā)基本上沒有三角形重疊,所以我們使用16x16的CubeMap來預計算各個方向上的三角形,這樣碰撞計算時可以快速查找到鄰近的三角形。


層間碰撞

游戲當中布料模擬的自碰撞是最難處理的部分,出于性能上的考慮,我們給出的方案如下:

  • 使用spatial hashing作為查找加速結(jié)構

  • 由美術預先分層,只考慮層之間粒子和三角形碰撞

  • 避免層之間卡住的情況,只計算粒子和三角形單法線方向的碰撞

由美術預先對布料進行分層,只考慮這些層之間的碰撞。使用散列哈希作為查找的加速結(jié)構,并且為了避免層之間卡住的情況,我們只考慮單法線方向的碰撞,如果已經(jīng)穿透了則略過,交給后面的步驟來修復。

實際實踐中,我們使用上一次substep的粒子位置來和當前的粒子位置進行碰撞,這樣可以很簡單的就解耦數(shù)據(jù)避免依賴。


層間穿透分離

對于層碰撞已經(jīng)穿透的部分,我們參考了untanging cloth的方式,使用了一個輕量的解決辦法,通過布料分層,從布料的固定點出發(fā),計算不同層級的邊和三角形的交點,因為我們的資產(chǎn)結(jié)構必定為一個uniform的網(wǎng)格,因此可以通過網(wǎng)格交點比較簡單的推測出其它粒子的推出三角形,最后對穿透的粒子-三角形對施加彈簧約束來解決穿透。在實踐中由于substep的關系,穿透的概率相對不大,因此我們采用分幀分塊執(zhí)行來減輕性能壓力。

2. 實時表演控制

戀與深空劇情表現(xiàn)中大部分的物理表現(xiàn),都是依托于cutscene來實現(xiàn)的各種物理效果的控制和調(diào)節(jié)。我們的工具同學開發(fā)和維護了一套非常強大的cutscene工具,在他們的基礎上我們開發(fā)了多種的功能軌道來具體調(diào)控物理效果。

這邊是我們一個動卡的Cutscene Physcs Track的例子,因為我們美術同學對于畫面表現(xiàn)扣的非常細,所以可以看到整個物理軌道的配置還是非常復雜的。


△Cutscene Physcs Track 示例

SmoothBlendPose Track

在表現(xiàn)當中,一個非常常見的問題就是動作瞬切切換帶來的物理抖動,無論是在劇情表演中還是換裝中,都經(jīng)常出現(xiàn)。

我們開發(fā)了一個較為通用的辦法,通過記錄初始物理姿態(tài),在切換的時候在初始姿態(tài)和當前姿態(tài)進行姿態(tài)插值計算,這樣就可以大幅度的緩解抖動,當然這個會帶來一些時間開銷,一般會在幾十毫秒左右,在大多數(shù)情況下都可以接受,提供一些參數(shù)例如插值次數(shù),插值的步幅大小來讓美術可以根據(jù)實際需要來去調(diào)整。


Pose Track

當然,SmoothBlendPose存在局限性,不能保證的完全順暢,特別是在一些劇情表演的復雜鏡頭切鏡下。我們還提供了一個比較直接的方案——離線直接保存某個時間幀的物理狀態(tài),在播放時,將保存的物理狀態(tài)直接應用到布料上,這樣就可以完美避免切鏡帶來的問題。


Edit Param Track

單一的物理資產(chǎn)是很難滿足劇情當中的各種不同場景下的表現(xiàn)的,比如有的時候希望布料軟一些硬一些,阻尼大一些小一些。我們提供編輯參數(shù)的軌道,通過這個軌道來實時的編輯修改參數(shù),絕大部分的參數(shù)都可以覆蓋大,可以非常方便的針對一小段時間幀進行修改。這個參數(shù)修改還可以用來做一些特殊的效果,比如動圖當中的利用編輯約束參數(shù)來實現(xiàn)的斷裂的效果。


Animation Track

完全的物理效果實際上不足以支持起整個畫面方方面面的表現(xiàn)的,很多時候表現(xiàn)上需要動畫和物理的結(jié)合來做一些互動。我們通過動畫軌道來實現(xiàn)動畫和物理的銜接和融合,精細的控制不同時間幀范圍下的表現(xiàn)。在實際制作流程當中,動作在dcc里和最終進引擎的表現(xiàn)差異是比較大的,包括一些引擎的實時rig系統(tǒng)修改后,動畫可能和其它地方有穿透,所以我們在動畫融合的基礎上,可以疊加上物理的碰撞效果,來避免一些穿插。

動圖當中展示是項鏈在物理和動畫的交互效果,包括從物理到動畫的狀態(tài)切換以及在不同動畫之間的切換。


Collider Track & Wind Track

Collider Track與Wind Track可以在cutscene中動態(tài)的創(chuàng)建、銷毀碰撞體和風場。根據(jù)不同畫面需求,靈活改變碰撞體和風場的狀態(tài)。通過角色、部件類型、還有布料的層分組來細節(jié)控制所要影響的對象范圍。

并且,碰撞體和風場軌道的絕大部分參數(shù)可以添加動畫幀控制,包括碰撞體的形態(tài)大小、風場的方向、范圍、強度、湍流等,方便美術把控物理效果,精準控制變化。

動圖當中是軌道膠囊體和風場的一些表現(xiàn)例子。


3. 基于Unity DOTS的開發(fā)

Jobs + Burst + Mathematics

DOTS這套工具非常強大,在C。我們的物理系統(tǒng)使用DOTS完全構建在C,功能迭代和debug都非常便利。目前來說我們最高可以支持2000+骨骼粒子的模擬。

當然,我們也針對性的在項目中,做了一些優(yōu)化進一步提升性能。


Cache Job

模擬中的job數(shù)量和依賴關系確定,job data并不頻繁變化,幀內(nèi)一般為相同數(shù)量和依賴關系的job組多次循環(huán)執(zhí)行,Unity Jobs 在發(fā)起任務時每次都需要重新創(chuàng)建job,雖然可以提前發(fā)起任務緩解,但是依然會卡主線程。并且在執(zhí)行完成job還需要clear?;谝陨系挠^察,我們開發(fā)了Cache Job的方案,預先創(chuàng)建好job data,然后每次執(zhí)行時復用,避免每次重新創(chuàng)建job帶來的性能開銷。

實現(xiàn)上比較簡單,因為是一個專用的結(jié)構,只考慮一些固定的使用場景。額外添加了一個Atomic Queue用來存cache job,使用fetch and add array 來存具體的job。右邊是worker執(zhí)行cache job的流程示意圖。


Neon Intrinsics

Burst會針對不同平臺生成高性能的simd code,在Burst Inspector中可以非常方便的查看。經(jīng)過檢查Burst Inspector和實機測試,在某些場合下也可以通過手寫Arm Neon Intrinsics來進一步提升性能。

這里給出例子是判斷向量是否存在大于0的元素的實現(xiàn)。



Dot(float4)

對于點乘,我這里列出了3種方式,使用neon intrinsics相比于mathematics在測試用例中可以獲得約30%的性能提升。如果目標機型支持armv8.2的話,可以使用新增的規(guī)約加法指令,來進一步的提升性能。一般來說現(xiàn)在市面上的大部分流行機型都是支持armv8.2的。


Transpose(float4x4)

對于轉(zhuǎn)置計算,可以看到mathematics生成的assembly code看起來性能是非常低的,通過手寫neon intrinsics, 可以得到一個巨大的性能提升。

如果只是純粹的需要轉(zhuǎn)置,可以直接使用交錯讀,這里這樣實現(xiàn)因為在我一般的實際使用中是通過對4個float4轉(zhuǎn)置來將點乘變成矢量乘。

這里只是給出這兩個項目里比較常用的例子。因為mathematics的代碼一般被內(nèi)聯(lián),在具體優(yōu)化時還需要根據(jù)代碼的上下文進行具體的優(yōu)化,可以結(jié)合burst inspector和真機測試來進行具體的性能測試。


4. 碰撞檢測模塊

為什么要脫離Unity成熟的物理模塊重新開發(fā)?

Unity 本身具有基于physx的一套成熟的物理模塊,而脫離Unity成熟的物理模塊重新開發(fā),主要基于以下考慮:

  • 戀與深空有相當多的不同種類的玩法,玩法間的layer設置相對獨立,非常希望能夠各自維護一套layer設置。

  • 有些模塊例如戰(zhàn)斗需要特殊的Trigger觸發(fā)和退出機制希望在底層就可以支持,對于執(zhí)行流程也希望有更靈活的控制。

  • 最后是在性能探索上我們也有一些想法,就是在僅需要碰撞檢測的情況下,利用DOTS能否提升性能?


《戀與深空》中的實現(xiàn)包括:

  • 基本實現(xiàn)了所有原生的碰撞查詢功能

  • 定制化的Update和Trigger邏輯

  • 線程安全的查詢接口,上層可以無負擔調(diào)用

  • 結(jié)合DOTS的輕量化結(jié)構實現(xiàn),在性能測試中,最高可獲得~15%的提升

查詢流程示例

由于真機上,我們實際的線程數(shù)量是固定的為4,所以對于memory allocator可以預先按照線程數(shù)量分配好,在分配時可以直接根據(jù)當前線程索引來獲取。

使用基于SAH的dynamic bvh作為broadphase加速結(jié)構,在插入、刪除以及超出范圍的移動時,對當前操作節(jié)點的鄰近的幾個層級節(jié)點進行旋轉(zhuǎn)平衡。

因為碰撞檢測的功能目標相對概括,對于精度要求沒有那么高,所以我們也適當?shù)臓奚恍┚群喕艘恍┡鲎矙z測算法來提升性能。


觸發(fā)流程示例

為了滿足戰(zhàn)斗模塊的需求,我們設計了特殊的trigger觸發(fā)邏輯,Trigger的 Enter 和 Exit必須要成對出現(xiàn),可以看到以下流程示意圖中,在a觸發(fā)b的函數(shù)中移除b后,會觸發(fā)所有和b存在overlap的collider,這里和unity原生的有所不同——原生的unity中在trigger邏輯中刪除掉b是不會觸發(fā)其它碰撞體的trigger的。最后,我們通過History計數(shù)來標記collider的版本,解決復用邏輯可能會導致的一些潛在問題。


特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺“網(wǎng)易號”用戶上傳并發(fā)布,本平臺僅提供信息存儲服務。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相關推薦
熱點推薦
崩潰!贖個“電雞”花3天,排隊300多號…

崩潰!贖個“電雞”花3天,排隊300多號…

廣州樓市發(fā)布
2026-01-06 21:16:12
2026年春節(jié),要暖到離譜!大年初一撞上七九,老輩人:60年頭回見

2026年春節(jié),要暖到離譜!大年初一撞上七九,老輩人:60年頭回見

米果說識
2026-01-06 21:35:09
船要沉了,和上錯了船的人無關

船要沉了,和上錯了船的人無關

求實處
2026-01-05 20:25:37
切爾西官宣新帥!短短4年:從魯尼助手到豪門主帥 簽6年半

切爾西官宣新帥!短短4年:從魯尼助手到豪門主帥 簽6年半

葉青足球世界
2026-01-06 19:15:47
教育部扔下重磅炸彈:2026年開始,全國一律不準再買校外商業(yè)試卷

教育部扔下重磅炸彈:2026年開始,全國一律不準再買校外商業(yè)試卷

趣文說娛
2026-01-05 17:49:32
5人反穿鰲山最新!2人身亡1人墜崖,救援隊曝猛料,一點也不無辜

5人反穿鰲山最新!2人身亡1人墜崖,救援隊曝猛料,一點也不無辜

游者走天下
2026-01-06 15:38:50
演員朱碧云現(xiàn)狀:美國精英生活,63歲依舊美麗,兒子成驕傲

演員朱碧云現(xiàn)狀:美國精英生活,63歲依舊美麗,兒子成驕傲

秋狝春苗夢
2026-01-06 17:36:54
吃相難看!海南房子到手后,何樹成繼續(xù)喊話趙本山:就讓你膈應我

吃相難看!海南房子到手后,何樹成繼續(xù)喊話趙本山:就讓你膈應我

梁瞠侃世界
2026-01-05 22:09:44
事實證明,多讀書就是有用!
你看看26歲女交警的采訪就知道了。

事實證明,多讀書就是有用! 你看看26歲女交警的采訪就知道了。

忠于法紀
2026-01-05 21:28:48
烏軍士兵:大霧天我們走到了敵方陣地,我們被困在地下室,外出時被俄軍發(fā)現(xiàn)并俘虜了

烏軍士兵:大霧天我們走到了敵方陣地,我們被困在地下室,外出時被俄軍發(fā)現(xiàn)并俘虜了

Ck的蜜糖
2026-01-07 05:53:07
上海啟動“穩(wěn)崗留工”工作

上海啟動“穩(wěn)崗留工”工作

中國青年報
2026-01-06 14:14:20
“嚴重傷害米粉們的感情”,小米深夜公布處罰結(jié)果:辭退涉事負責經(jīng)辦人員??

“嚴重傷害米粉們的感情”,小米深夜公布處罰結(jié)果:辭退涉事負責經(jīng)辦人員??

每日經(jīng)濟新聞
2026-01-06 23:39:06
研究:特朗普關稅未明顯推高美國通脹 關稅收入已開始下滑

研究:特朗普關稅未明顯推高美國通脹 關稅收入已開始下滑

財聯(lián)社
2026-01-06 22:28:08
重創(chuàng)!曼城7000萬中衛(wèi)賽季報銷+無緣世界杯,剩2中衛(wèi)欲急購英國腳

重創(chuàng)!曼城7000萬中衛(wèi)賽季報銷+無緣世界杯,剩2中衛(wèi)欲急購英國腳

我愛英超
2026-01-06 06:56:08
《紅白》驚見不雅畫面!女歌手肉色戰(zhàn)袍「像沒穿」正面開腿…挨轟低俗

《紅白》驚見不雅畫面!女歌手肉色戰(zhàn)袍「像沒穿」正面開腿…挨轟低俗

ETtoday星光云
2026-01-05 09:50:07
心理學有個「柯立芝效應」:和伴侶在一起久了突然覺得沒感覺,不是你不愛Ta,也不是討厭Ta,而是柯立芝效應

心理學有個「柯立芝效應」:和伴侶在一起久了突然覺得沒感覺,不是你不愛Ta,也不是討厭Ta,而是柯立芝效應

Fri心理
2026-01-05 19:38:52
恥辱5連?。BA最大的偽強隊,四巨頭成擺設,你們真的該散伙了

恥辱5連??!NBA最大的偽強隊,四巨頭成擺設,你們真的該散伙了

籃球看比賽
2026-01-06 13:01:20
420枚ATACMS導彈、82套海馬斯系統(tǒng),一票裝船,直指東南沿海。

420枚ATACMS導彈、82套海馬斯系統(tǒng),一票裝船,直指東南沿海。

安安說
2026-01-05 15:27:24
醫(yī)生研究發(fā)現(xiàn):糖尿病最危險的信號,不是腿疼腳疼,而是這5癥狀

醫(yī)生研究發(fā)現(xiàn):糖尿病最危險的信號,不是腿疼腳疼,而是這5癥狀

搖感軍事
2026-01-06 21:37:28
特斯拉開卷了 !剛官宣這騷操作,炸翻全網(wǎng)!

特斯拉開卷了 !剛官宣這騷操作,炸翻全網(wǎng)!

科技狐
2026-01-06 22:39:58
2026-01-07 06:39:00
游娛fan incentive-icons
游娛fan
精彩游戲資訊
1818文章數(shù) 463關注度
往期回顧 全部

游戲要聞

魔獸世界:時光服再次魔改,副本資源遭移除,刷子還不放棄嗎?

頭條要聞

特朗普:若輸中期選舉 我可能被彈劾

頭條要聞

特朗普:若輸中期選舉 我可能被彈劾

體育要聞

從NBA最菜首發(fā)控衛(wèi),到NBA最強喬治

娛樂要聞

2026年央視春晚彩排照曝光!

財經(jīng)要聞

50萬億存款"洪流"將至 四大去向引關注

科技要聞

速看!黃仁勛萬字實錄:甩出"物理AI"王牌

汽車要聞

摩登出街潮品 實拍奇瑞QQ冰淇淋女王版

態(tài)度原創(chuàng)

親子
藝術
本地
公開課
軍事航空

親子要聞

流感季寶媽必看:網(wǎng)上說奧司他韋致幻覺純屬誤導

藝術要聞

傲雪寒梅為君開。

本地新聞

云游內(nèi)蒙|初見呼和浩特,古今交融的北疆都會

公開課

李玫瑾:為什么性格比能力更重要?

軍事要聞

美稱對“占領”委內(nèi)瑞拉保留選擇權

無障礙瀏覽 進入關懷版