遊戲中的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遊戲
- 根本停不下來的“真·遊戲毒品 ”城市營造遊戲(中):百花齊放遊戲
- 歸納貼:武俠小說和遊戲中的武功效果(轉)遊戲
- App Annie:《夢幻花園》是韓國市場中收入最高的益智遊戲APP遊戲
- 如何讓玩家在遊戲中花錢? 一個完善的促銷系統就能搞定遊戲
- 當國風遊戲遇上團扇手作,傳說中的合合島大玩國風“花活”遊戲
- 剪貼簿中的觀察者(Observer)模式Server模式
- AD中如何使用特殊貼上和陣列貼上陣列
- UltraEdit中貼上問題
- 樂隊遊戲與它曇花一現的黃金年代遊戲
- 「用愛發電」的百度貼吧遊戲吧主遊戲
- Linux 系統中的Samba配置(轉貼)LinuxSamba
- 關於驅動程式中的ioctl (轉貼)
- 容器flappybird遊戲——圖文操作指引貼APP遊戲
- YouGov:40%的父母計劃花更多錢購買遊戲禮物Go遊戲
- 識別和避免反彙編中遇到的花指令
- 除了打小遊戲之外,電子遊戲的載入介面還被玩出過多少花樣?遊戲
- 從山海鏡花看日式遊戲美術設計遊戲
- 分析師:玩家在主機硬體上花費越來越多 遊戲花費變少遊戲
- 影像處理技術:影像切割、標籤、貼紙花字,超細開發詳解
- 【經驗貼】如何躲避專案管理中的“刺客”?專案管理
- 【小貼士】探一探javascript中的replaceJavaScript
- 《The Clean Coder》中的「Clean」如何譯?【已結貼】
- 複製貼上文字中的 nbsp怎麼去掉?
- 購買遊戲花費的70美元 最終究竟到了誰的手裡?遊戲
- 遊戲演算法整理(貼圖完整版)遊戲演算法
- 遊戲公司競逐雲遊戲千億藍海 “開花結果”尚需時日遊戲
- vue 中實現複製貼上Vue
- SLG搶量有多燒錢?這款遊戲一年花5億、兩年花8億遊戲
- NPD:所有年齡段的美國人在電子遊戲上的花費都在增加遊戲
- 我在淘寶花5塊錢買了一千個遊戲遊戲
- Linux下命令列中的複製和貼上Linux命令列
- 遊戲中的夥伴遊戲
- 廢土遊戲遍地開花,它們身上都有這部電影的影子遊戲
- 口袋妖怪原生花3:華麗的冒險 for Mac(角色扮演類遊戲)Mac遊戲
- Whitethorn公開收支明細,獨立遊戲發行商是如何花錢的?遊戲
- 竹子開花的“策略”
- 不用花錢的傳奇手機遊戲 免費回收可以賺錢的傳奇手遊遊戲