夜夜躁很很躁日日躁麻豆,精品人妻无码,制服丝袜国产精品,成人免费看www网址入口

網(wǎng)易首頁(yè) > 網(wǎng)易號(hào) > 正文 申請(qǐng)入駐

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

戀與深空天黑請(qǐng)睜眼

0
分享至

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

GPU Driven

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

同時(shí),我們會(huì)預(yù)計(jì)算每個(gè)Group的Instance Offset,并將其存儲(chǔ)到Parameter的InstanceStart項(xiàng),全程只綁定一份Instance Buffer。


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

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

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

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

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

單DrawCall性能優(yōu)化

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

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

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

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

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

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

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

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

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

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

    • 只需改變PerMaterialBuffer時(shí),改用簡(jiǎn)化后的專用接口。

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

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

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

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

我們?cè)诘投税沧吭O(shè)備上測(cè)試了5000個(gè)DrawCall的耗時(shí)。使用引擎原生的渲染時(shí),渲染線程的耗時(shí)是34.79ms。當(dāng)我們對(duì)Buffer提交與渲染邏輯進(jìn)行優(yōu)化后,耗時(shí)降低到22.97ms。在進(jìn)一步優(yōu)化RHI調(diào)用次數(shù)后,耗時(shí)進(jìn)一步大幅降至了11.8ms。最終我們?cè)贒rawCall數(shù)量不變的前提下,讓CPU耗時(shí)減少到了原來(lái)的1/3以下。


其他優(yōu)化嘗試Benchmark場(chǎng)景測(cè)試結(jié)果

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

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

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

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

2. 光照方案

光照方案

  • 前向渲染管線:

我們?cè)陧?xiàng)目中選擇使用前向渲染管線,包含以下多方面考慮:首先,前向管線在應(yīng)對(duì)美術(shù)復(fù)雜且多變的需求方面有其優(yōu)勢(shì),我們不需要擔(dān)心一些材質(zhì)屬性的添加是否會(huì)導(dǎo)致GBuffer膨脹。

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

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

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

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


  • Vulkan版本管線改進(jìn)

我們?cè)谖磥?lái)的Vulkan版本的管線中增加了基于Subpass的Light Pre-Pass。

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

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

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

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

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


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

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

  • GI

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

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


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

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

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

3. 陰影優(yōu)化

功能設(shè)計(jì)

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

  • 三級(jí)CSM+角色特寫陰影/多角色POSM:3級(jí)Cascade的CSM+1級(jí)角色專屬的特寫陰影,在某些多角色場(chǎng)景時(shí)會(huì)使用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信息。

距離剔除

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

因?yàn)樵谟?jì)算陰影時(shí)要采樣depth,我們需要兩份depth分別用于Test與Sample,我們會(huì)在NativeRenderPass中拷貝一份Memoryless的Depth Buffer用于Test,盡量避免額外的讀寫帶寬。

半影區(qū)域檢測(cè)

我們?cè)黾恿税胗皡^(qū)域檢測(cè)功能,先在1/4分辨率下計(jì)算一次PCF,隨后在全分辨率Shadow Pass里采樣1/4 mask,僅對(duì)shadow值處于中間區(qū)域的像素執(zhí)行全分辨率PCF,在保證效果的同時(shí)降低計(jì)算量。

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

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


逐像素bias

我們利用Receiver Plane Depth Bias算法實(shí)現(xiàn)了逐像素的Shadow Bias。它的原理也比較簡(jiǎn)單,首先對(duì)屏幕空間shadow coordinates偏導(dǎo)應(yīng)用二維鏈?zhǔn)椒▌t,求出陰影空間偏導(dǎo)。


利用偏導(dǎo)與PCF采樣偏移我們可以求出bias值。對(duì)于中心點(diǎn)來(lái)說(shuō),我們?cè)黾恿?個(gè)像素偏移的bias結(jié)果作為起始bias。

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


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

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

Scrolling Cached Shadow Map

針對(duì)DrawCall較多的場(chǎng)景,我們還嘗試了Scrolling Cached Shadow Map,具體包括:

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

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

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

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


1. 角色光照方案

在角色光照方案中,相信大家多多少少都會(huì)遇到以下幾類問(wèn)題:


對(duì)這些問(wèn)題進(jìn)行拆解,則可以總結(jié)為以下3個(gè)需求:


基于以上需求,我們進(jìn)行了具體角色光照方案設(shè)計(jì)。

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

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

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

  • 同時(shí)預(yù)留了兩個(gè)額外光給角色,額外光可以是任意的點(diǎn)光和射燈組合,可以正常照亮范圍內(nèi)的角色和場(chǎng)景物件( 因?yàn)橐粋€(gè)2米的格子最多四盞額外光,所以將2個(gè)燈光劃分給角色)。

間接光我們使用Unity的LightProbe系統(tǒng)來(lái)創(chuàng)建探針,自己實(shí)現(xiàn)了保存間接光到探針里的部分,把場(chǎng)景的探針和角色的探針?lè)珠_兩套,分別存儲(chǔ)和使用;

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


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

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


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

可銜接光效果如下所示:


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


2. 特寫陰影

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


通過(guò)以下動(dòng)圖可以看到,角色原本整個(gè)都在主光陰影里,打開特寫陰影的時(shí)候變成了可以被主光正常照亮,就是因?yàn)樘貙戧幱靶薷牧私们衅矫?;也就是說(shuō)我們的特寫陰影是一張單獨(dú)可調(diào)參數(shù)的陰影圖,具體參數(shù)包括遠(yuǎn)近裁切平面,最遠(yuǎn)距離,還有使用哪一盞光和往往最讓人頭疼的bias。


3. 皮膚細(xì)節(jié)

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

  • 臉紅效果

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


為了模擬這個(gè)過(guò)程,我們采取了以下方式,使畫面更加生動(dòng)和真實(shí):

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

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

    • 預(yù)存變化過(guò)程:臉紅的過(guò)渡過(guò)程分通道記錄在對(duì)應(yīng)曲線上,實(shí)現(xiàn)自然的情緒表達(dá)。

  • 流汗效果

我們游戲里提供了運(yùn)動(dòng)陪伴功能,男主會(huì)進(jìn)行一些運(yùn)動(dòng)訓(xùn)練的陪伴,因此也就需要提供相應(yīng)的流汗效果。具體實(shí)現(xiàn)主要通過(guò)以下三個(gè)方面:

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

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

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

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


△計(jì)算汗滴生成位置并修改汗滴位置粗糙度


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


△模擬汗滴下落的軌跡


△運(yùn)動(dòng)陪伴系統(tǒng)流汗效果


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

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

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

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

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

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

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


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

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

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

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

骨骼約束方案

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


因此,我們?cè)诠趋兰s束方案上,選擇了基于Cosserat Rod的骨骼約束。它的優(yōu)點(diǎn)包括:

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

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

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

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


布料與角色連接

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

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

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

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

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


碰撞方案

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

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

在narrow phase 當(dāng)中,我們不直接生成contact,而是緩存碰撞體對(duì),在substep中再具體的解決,因?yàn)槲覀儾捎玫膕ub step的優(yōu)點(diǎn),大多數(shù)情況下直接使用DCD就可以避免一些快速運(yùn)動(dòng)下造成的穿透問(wèn)題,不需要引入ccd或者predictive contact等一些操作。


  • Mesh Collider實(shí)現(xiàn)

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

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

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


Face Collider

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


層間碰撞

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

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

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

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

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

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


層間穿透分離

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

2. 實(shí)時(shí)表演控制

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

這邊是我們一個(gè)動(dòng)卡的Cutscene Physcs Track的例子,因?yàn)槲覀兠佬g(shù)同學(xué)對(duì)于畫面表現(xiàn)扣的非常細(xì),所以可以看到整個(gè)物理軌道的配置還是非常復(fù)雜的。


△Cutscene Physcs Track 示例

SmoothBlendPose Track

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

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


Pose Track

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


Edit Param Track

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


Animation Track

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

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


Collider Track & Wind Track

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

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

動(dòng)圖當(dāng)中是軌道膠囊體和風(fēng)場(chǎng)的一些表現(xiàn)例子。


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

Jobs + Burst + Mathematics

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

當(dāng)然,我們也針對(duì)性的在項(xiàng)目中,做了一些優(yōu)化進(jìn)一步提升性能。


Cache Job

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

實(shí)現(xiàn)上比較簡(jiǎn)單,因?yàn)槭且粋€(gè)專用的結(jié)構(gòu),只考慮一些固定的使用場(chǎng)景。額外添加了一個(gè)Atomic Queue用來(lái)存cache job,使用fetch and add array 來(lái)存具體的job。右邊是worker執(zhí)行cache job的流程示意圖。


Neon Intrinsics

Burst會(huì)針對(duì)不同平臺(tái)生成高性能的simd code,在Burst Inspector中可以非常方便的查看。經(jīng)過(guò)檢查Burst Inspector和實(shí)機(jī)測(cè)試,在某些場(chǎng)合下也可以通過(guò)手寫Arm Neon Intrinsics來(lái)進(jìn)一步提升性能。

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



Dot(float4)

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


Transpose(float4x4)

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

如果只是純粹的需要轉(zhuǎn)置,可以直接使用交錯(cuò)讀,這里這樣實(shí)現(xiàn)因?yàn)樵谖乙话愕膶?shí)際使用中是通過(guò)對(duì)4個(gè)float4轉(zhuǎn)置來(lái)將點(diǎn)乘變成矢量乘。

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


4. 碰撞檢測(cè)模塊

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

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

  • 戀與深空有相當(dāng)多的不同種類的玩法,玩法間的layer設(shè)置相對(duì)獨(dú)立,非常希望能夠各自維護(hù)一套layer設(shè)置。

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

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


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

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

  • 定制化的Update和Trigger邏輯

  • 線程安全的查詢接口,上層可以無(wú)負(fù)擔(dān)調(diào)用

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

查詢流程示例

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

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

因?yàn)榕鲎矙z測(cè)的功能目標(biāo)相對(duì)概括,對(duì)于精度要求沒(méi)有那么高,所以我們也適當(dāng)?shù)臓奚恍┚群?jiǎn)化了一些碰撞檢測(cè)算法來(lái)提升性能。


觸發(fā)流程示例

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


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

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.

相關(guān)推薦
熱點(diǎn)推薦
鄭麗文話風(fēng)變了:避談統(tǒng)一,轉(zhuǎn)向民族復(fù)興大棋局,網(wǎng)友:太滑頭!

鄭麗文話風(fēng)變了:避談統(tǒng)一,轉(zhuǎn)向民族復(fù)興大棋局,網(wǎng)友:太滑頭!

小lu侃侃而談
2025-10-25 17:48:10
鏡報(bào):避免重蹈覆轍,拉特克利夫已經(jīng)明確表示不會(huì)引進(jìn)萊萬(wàn)

鏡報(bào):避免重蹈覆轍,拉特克利夫已經(jīng)明確表示不會(huì)引進(jìn)萊萬(wàn)

雷速體育
2025-10-26 10:28:07
男性更容易患腸癌?醫(yī)生:不是食物的問(wèn)題,一般都有這三個(gè)壞習(xí)慣

男性更容易患腸癌?醫(yī)生:不是食物的問(wèn)題,一般都有這三個(gè)壞習(xí)慣

原來(lái)仙女不講理
2025-10-26 16:24:58
李成鋼:中美經(jīng)貿(mào)團(tuán)隊(duì)就雙方關(guān)注的經(jīng)貿(mào)議題進(jìn)行了深入、坦誠(chéng)的討論和交流

李成鋼:中美經(jīng)貿(mào)團(tuán)隊(duì)就雙方關(guān)注的經(jīng)貿(mào)議題進(jìn)行了深入、坦誠(chéng)的討論和交流

澎湃新聞
2025-10-26 17:37:12
突發(fā)特訊!馮德萊恩通告中國(guó):若談不攏,必要時(shí)將動(dòng)用所有可用手段,罕見措辭引發(fā)高度關(guān)注

突發(fā)特訊!馮德萊恩通告中國(guó):若談不攏,必要時(shí)將動(dòng)用所有可用手段,罕見措辭引發(fā)高度關(guān)注

在新加坡生活
2025-10-26 13:22:31
在現(xiàn)實(shí)中,為什么大部分的底層小人物都特別喜歡宏大敘事呢?

在現(xiàn)實(shí)中,為什么大部分的底層小人物都特別喜歡宏大敘事呢?

翻開歷史和現(xiàn)實(shí)
2025-10-26 12:45:20
這兩國(guó)曾發(fā)下毒誓:“誰(shuí)敢動(dòng)中國(guó)我就滅誰(shuí)!”,如今對(duì)華反目成仇

這兩國(guó)曾發(fā)下毒誓:“誰(shuí)敢動(dòng)中國(guó)我就滅誰(shuí)!”,如今對(duì)華反目成仇

小lu侃侃而談
2025-10-25 17:51:38
李一桐私下吊帶身材也這么火辣嗎?

李一桐私下吊帶身材也這么火辣嗎?

東方不敗然多多
2025-10-19 08:32:09
離譜!中國(guó)女子大盜法國(guó)博物館,竟然只用了最簡(jiǎn)單的辦法

離譜!中國(guó)女子大盜法國(guó)博物館,竟然只用了最簡(jiǎn)單的辦法

公子故事會(huì)
2025-10-23 18:29:49
麗文團(tuán)隊(duì)人員確定,其中一人能讓賴清德膽顫!果然不負(fù)大陸期待

麗文團(tuán)隊(duì)人員確定,其中一人能讓賴清德膽顫!果然不負(fù)大陸期待

生活魔術(shù)專家
2025-10-26 16:10:39
重慶銅梁龍vs石家莊功夫:兩隊(duì)均雙外援出戰(zhàn),向余望首發(fā)

重慶銅梁龍vs石家莊功夫:兩隊(duì)均雙外援出戰(zhàn),向余望首發(fā)

懂球帝
2025-10-26 18:26:15
斷供19天,中國(guó)恢復(fù)安世供貨,不賣給國(guó)外,并且必須用人民幣結(jié)算

斷供19天,中國(guó)恢復(fù)安世供貨,不賣給國(guó)外,并且必須用人民幣結(jié)算

來(lái)科點(diǎn)譜
2025-10-26 09:26:01
搞笑,杰倫·布朗的發(fā)際線在凱爾特人輸尼克斯的比賽似乎途脫落

搞笑,杰倫·布朗的發(fā)際線在凱爾特人輸尼克斯的比賽似乎途脫落

好火子
2025-10-25 22:48:29
普通家庭的真實(shí)存款有多少?網(wǎng)友:夫妻倆月收入3萬(wàn),存款有40個(gè)

普通家庭的真實(shí)存款有多少?網(wǎng)友:夫妻倆月收入3萬(wàn),存款有40個(gè)

解讀熱點(diǎn)事件
2025-09-20 00:05:08
他本是東北最強(qiáng)殺手,逃亡到京城后,成了當(dāng)?shù)匾沟甑耐?>
    </a>
        <h3>
      <a href=曉艾故事匯
2024-06-29 21:23:15
楊振寧告別儀式曝光49歲翁帆近照,杜致禮親妹所言果然不虛!

楊振寧告別儀式曝光49歲翁帆近照,杜致禮親妹所言果然不虛!

元爸體育
2025-10-26 17:27:53
年僅28歲的徐志摩是如何看穿蘇俄“一切都是演戲”的?

年僅28歲的徐志摩是如何看穿蘇俄“一切都是演戲”的?

霹靂炮
2025-10-20 23:21:24
李成鋼:中美就有關(guān)議題形成了初步共識(shí)

李成鋼:中美就有關(guān)議題形成了初步共識(shí)

新京報(bào)政事兒
2025-10-26 17:27:04
還在讀高中!拜仁17歲男孩奇幻4天:2天上學(xué)+2天踢球 2場(chǎng)2球2破荒

還在讀高中!拜仁17歲男孩奇幻4天:2天上學(xué)+2天踢球 2場(chǎng)2球2破荒

風(fēng)過(guò)鄉(xiāng)
2025-10-26 12:19:17
浙江衢州:57名干部因考核結(jié)果較差被調(diào)整崗位,389名干部成績(jī)突出獲提任晉升

浙江衢州:57名干部因考核結(jié)果較差被調(diào)整崗位,389名干部成績(jī)突出獲提任晉升

政知新媒體
2025-10-26 16:59:27
2025-10-26 20:23:00
游娛fan incentive-icons
游娛fan
精彩游戲資訊
1734文章數(shù) 462關(guān)注度
往期回顧 全部

游戲要聞

《天外世界2》搶先版玩家比《宣誓》還少:峰值沒(méi)過(guò)萬(wàn)

頭條要聞

女子參加荒野求生半個(gè)月灰頭土臉瘦成"閃電" 本人發(fā)聲

頭條要聞

女子參加荒野求生半個(gè)月灰頭土臉瘦成"閃電" 本人發(fā)聲

體育要聞

曼聯(lián):計(jì)劃有變!目標(biāo)爭(zhēng)冠!

娛樂(lè)要聞

邁克爾·杰克遜女兒拿到4.6億仍要索賠

財(cái)經(jīng)要聞

李成鋼:中美就有關(guān)議題形成了初步共識(shí)

科技要聞

誰(shuí)“殺死”了新能源汽車周榜?

汽車要聞

兩條腿走得更遠(yuǎn) 哈弗H6L為燃油SUV上分

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

本地
親子
數(shù)碼
教育
軍事航空

本地新聞

這個(gè)秋天,一起來(lái)粉上漓渚!所有風(fēng)景只為等你

親子要聞

兒童癲癇用藥要小心

數(shù)碼要聞

蘋果 M5 MacBook Pro SSD 讀寫速度較 M4 款最高提升 211%

教育要聞

女生作文《自畫像》火了,孤芳自賞卻不得分,老師評(píng)語(yǔ):撕了重寫

軍事要聞

西方多國(guó)就烏克蘭問(wèn)題發(fā)聲:堅(jiān)決支持立即停火

無(wú)障礙瀏覽 進(jìn)入關(guān)懷版 熟妇与小伙子mature老熟| 色婷婷亚洲婷婷六月中六字幕| 国产精品无码翘臀在线观看| 大胆国模一品一二三区| 欧洲精品色在线观看| 东方四虎www在线观看中文字幕| 亚洲国产一区二区三区四| 俺来也俺也去Av| 疯狂做受XXXX高潮国产| 欧美性生活高潮视频网| 中文字幕乱码人妻二区三区| 内射干少妇亚洲69xxx| 精品久久久久久无码免费| 波多野结衣办公室奸情| 久久久久亚洲AV无码一超级粉嫩无码 | 欧美人和黑人牲交网站上线| 亚洲av激情无码专区在线下载| 亚洲午夜国产精品无码老牛影视| 好吊日妞干网| 亚洲成女人图区一区二区| 国产无码综合在线观看| 91密桃精品国产91久久| 四虎无码在线观看| 国产日产韩国精品视频,| 色色院澋97| 国产一区二区在线有码| 91人妻人人操人人爽| 中字无码在线| 日本两人免费观看的视频| 久久性爱视频| 亚洲永久资源站| 久久久亚洲AⅤ无码精品爱豆传媒| 48多岁辽宁老熟女1| 亚洲第一AV片精品堂在线观看| 国产一精品一aⅴ免费| 亚洲无码先锋| 国产熟女大屁股喷水91精品| 精品自拍偷拍一区二区三区| 亚洲午夜粉嫩AV| 小泽玛利亚一区二区免费| 色欧美与xxxxx|