遊戲中的Decal(貼花)
在遊戲中,decal是一種非常常見的效果,常用來實現彈孔,血跡,塗鴉等效果。最近研究了下Decal在遊戲引擎中的實現方式,大致總結了一下:
1.基於面片實現:
直接用一個Quat的mesh,加上一張貼圖,簡單直觀的實現。
缺點:只能在平面上貼。
2.修改貼圖:
將物體的材質貼圖替換成原貼圖和decal貼圖的混合,適用於靜態批量的物體
缺點:只適用於靜態物體
3.基於SubMesh:
先獲取跟目標投影相交的mesh,然後將mesh根據投影框進行裁剪
1.獲取所有可能和投影框相交的mesh,一般遊戲引擎都會有Octree或BVH儲存mesh的aabb,這一步簡單獲取aabb相交的mesh即可。
2.將mesh的頂點資料變換到投影框的三維空間中,這樣一來是方便裁剪,二來是裁剪完成後可以將變換後的座標值直接作為uv值使用。
3.得到相交的三角形片:
判斷每個點是否在投影框內,如果三角形有任意一個點在框內,則認為三角形與投影框相交。當然這種方法會漏掉一些三角形,比如這中情況:當然如果mesh較小以及要求不精細的話也沒有太大問題。
三角形頂點都不在框內,但是和框相交
比較嚴謹的求交演算法可以使用SAT演算法,參考 RealTimeRendering4 22.12 或者這個https://gdbooks.gitbooks.io/3dcollisions/content/Chapter4/aabb-triangle.html.
4.將所有相交的三角形片,合併成新的IndexBuffer,使用新的decal的紋理重新渲染一次,UV可以直接取對映到框中的xy值,當然要注意在shader中把uv 0~1之外的部分clip掉
5.如果你想的話,也可以對處在邊界,不完全在框內部的三角形進行裁剪,最後整理頂點生成新的mesh.
方法如下:
簡單的逐邊裁剪:
逐邊裁剪
也可以一次性裁剪所有的方向,參考下面的演算法(來自<計算機圖形學第三版>6.8.1)
一次性裁剪所有邊
缺點:比較適用於靜態的物體,建立過程可能耗時較長
4.基於Multi-Pass實現:
和上面方法很相似
1.獲取所有相交的mesh;
2.在mesh正常渲染結束後,再渲染一次,使用decal的shader,向shader中傳入一個ClipToDecal的矩陣(=ClipToWorld * WorldToDecal),在FS中計算計算對映到decal框中的座標,取決於具體的實現,可以將xy座標作為uv,以及裁剪掉uv0~1之外的部分,將decal渲染出來。
Unity的built-in管線中的Projector就是使用的這種方式。
缺點:如果投影框與多個mesh相交,或者mesh很大,則會產生很大的效能消耗。
5.修改渲染shader實現
判斷decal框和某個mesh相交時,將decal標記為需要渲染。修改mesh的shader,傳入一個或多個decal投影框矩陣+數張decal貼圖。FS得到原始的輸出顏色後,再根據decal拿到的顏色進行混合,如果同時有多個Decal,則需要不同數量改變shader變體。
缺點:需要大量調整shader,複雜繁瑣,而且一個mesh上的decal數量在執行時發生變化時,需要動態編譯shader變體。
6.基於後處理實現:
將decal整體作為一個長方體進行渲染兩次來對目標進行貼花
1.首先正常渲染其他的物體,拿到正常渲染的buffer和depth buffer.
2.將投影框作為一個長方體進行渲染,關閉Face Cull,將depth test設定為GreatEqual,輸出一個標誌位到 stencil buffer(或者任意其他可以標誌畫素點的方式),不需要輸出顏色值
3.再次將投影框作為長方體渲染,開啟Face Cull(只繪製長方形靠前的三個面),再上一步中stencil buffer測試通過的位置繪製,與前面方法不同的是,當前畫素點的 WorldPosition 通過從depth buffer中讀取然後反變換獲得(後處理中非常常用的方法).
兩種情況下decal繪製示意圖
投影面在靠後的位置
投影在靠前的位置
缺點:不支援光照
7.Deferred實現
大致和上面的方法相同
deferred 渲染管線中渲染所有gbuffer之後
和上一個方法中講到的一樣,同樣是先渲染長方體,寫入stencil buffer,然後再次渲染長方體,根據stencil buffer來改變gbuffer中的資料,根據需要選擇修改basecolor,normal等;
因為gbuffer被修改,後面的光照計算會產生decal的效果。
UE4中的DefferedDecal,就是這種方法(未使用Dbuffer時)
缺點: 只能用於Deferred,不支援烘培光(因為烘培光是在渲染gbuffer時加上的).
8.Dbuffer
先進行depth prepass渲染深度圖
用上面提到的方法將decal渲染到類似gbuffer的dbuffer上,然後在渲染gbuffer時(或者forward渲染時),直接應用同樣位置對dbuffer進行取樣,融合到gbuffer中,可以支援烘培光,支援deferred,forward管線。
Unity的HDRP以及UE4中的DeferredDecal(使用Dbuffer),使用該方法
UE4中的Decal Material,當選擇使用Dbuffer渲染時,會根據不同的型別來使用不同數量的Dbuffer Render Target
缺點:很大的效能消耗
9.常見的問題
1.垂直角度投影時可能出現這樣的拉伸,可以加上一個角度判斷,丟棄角度超過某個閾值的畫素。
2.可能需要在邊緣處加上一些fade off的效果,防止突兀的邊界。
3.blend方式,decal材質可以提供base color,normal等屬性,decal是半透明時,需要仔細考慮和原圖base color等的混合方式,normal 需要變換下切空間後再進行混合。
4.一般情況下decal無法支援帶骨骼動畫的物體。
作者:TC130
專欄地址:https://zhuanlan.zhihu.com/p/100748588
相關文章
- AI生成遊戲中基於物理的渲染(PBR)貼圖探索AI遊戲
- 根本停不下來的“真·遊戲毒品 ”城市營造遊戲(中):百花齊放遊戲
- 容器flappybird遊戲——圖文操作指引貼APP遊戲
- App Annie:《夢幻花園》是韓國市場中收入最高的益智遊戲APP遊戲
- 「用愛發電」的百度貼吧遊戲吧主遊戲
- 如何讓玩家在遊戲中花錢? 一個完善的促銷系統就能搞定遊戲
- 除了打小遊戲之外,電子遊戲的載入介面還被玩出過多少花樣?遊戲
- 遊戲中的夥伴遊戲
- “遊戲中的遊戲世界”——遊戲副本的起源與發展史遊戲
- 樂隊遊戲與它曇花一現的黃金年代遊戲
- 遊戲公司競逐雲遊戲千億藍海 “開花結果”尚需時日遊戲
- 快手釋出首個遊戲短視訊補貼政策,進軍“硬核“遊戲內容遊戲
- 當國風遊戲遇上團扇手作,傳說中的合合島大玩國風“花活”遊戲
- YouGov:40%的父母計劃花更多錢購買遊戲禮物Go遊戲
- 從山海鏡花看日式遊戲美術設計遊戲
- 遊戲中的“瘟疫史”遊戲
- 遊戲中<loading>的思考遊戲
- 遊戲中的Volumetric Rendering遊戲
- 遊戲開發中遊戲效能的最佳化遊戲開發
- 乾貨貼:俯瞰2021遊戲出海營銷最新動向遊戲
- 中國出海品牌50強:16款遊戲品牌上榜,知名信賴度兩開花遊戲
- 購買遊戲花費的70美元 最終究竟到了誰的手裡?遊戲
- 不用花錢的傳奇手機遊戲 免費回收可以賺錢的傳奇手遊遊戲
- 步步為營,NExT Studios的新作怎樣把肉鴿遊戲玩出花?iOS遊戲
- 分析師:玩家在主機硬體上花費越來越多 遊戲花費變少遊戲
- 回合制遊戲中的10種遊戲平衡手段遊戲
- 中國元素海外開花,打造西遊新玩法
- 日本遊戲中的中國武術遊戲
- 元遊戲(Metagame)中的“沉默”遊戲GAM
- 喵的Unity遊戲開發之路 - 推球:遊戲中的物理Unity遊戲開發
- 入行掃盲貼:<遊戲分析與評測>該怎麼做?遊戲
- 廢土遊戲遍地開花,它們身上都有這部電影的影子遊戲
- Whitethorn公開收支明細,獨立遊戲發行商是如何花錢的?遊戲
- 遊戲與烏托邦:《蚱蜢》中的遊戲哲學(四)遊戲
- 遊戲基礎知識——遊戲中“屍體”的設計遊戲
- 我在淘寶花5塊錢買了一千個遊戲遊戲
- 遊戲出海百花齊放 邊鋒bfun乘風破浪遊戲
- 資深技術貼:自動去光照,完美融入遊戲場景的黑科技遊戲