2020年6月19日 星期五

不一樣的戰爭策略遊戲陣營線做法

一般的做法,不外乎是用grid或mesh來畫,通常這樣的做法比較無法跟物件本身的外形相合,另外也會處理交集的邏輯運算,比較麻煩… 比方:


















或著是這樣:






















後來仔細想想,其實應該是直接可以用索貝爾運算子來計算交集的部份來做勾邊處理,這樣一來又可以不用花CPU的時間來處理圍起來的邏輯,另外也可以支持原模型的形狀,而不用局限於特定的shape形狀,結果如下:

2020年3月26日 星期四

Custom URP Camera Stacking Processing

URP 一開始就是將3D及UI的解析度拆開來的架構設計(以達到3D降低分辨率,UI又可保持原生解析度),自從Camera Stack Processing功能出來後,許多專案都開始用上這個功能,但經過測試後,發現對於UI部份的處理不是很友善,尤其是像有專案想用Camera模式來渲染UI,會造成模糊的問題。

當降低RenderScale的時候來優化3D渲染,會造成Camera Stack Process渲染的UI也會跟著降,而變糊…狀況如下:























目前筆者自己的Renderer是自己寫的,不是使用原生的ForwardRenderer,所以就很方便了客製化處理了這一部份,採用直接渲染到屏幕的作法,而不是渲染到原本那張降過解析度的RenderTexture,效果如下:























如果有類似這種特殊需求,應該算是一種客製化Renderer的需求吧!早點習慣URP提供給你寫自己Renderer的架構,來滿足專案的各種需求才是長遠之道…

相關影片如下:

2020年2月4日 星期二

俯視視角巨量物件渲染優化

傳統巨量物件優化,大部份都是用GPUInstance來解決,但由於這部份只有解決vertex傳輸頻寬的問題,如果拿來使用在面數較多的物件上,沒有做好view frustum culling的話,會導致vertex shader processing的瓶頸。

GPUInstance又分為AutoInstance及ManualInstance,前者是透過MeshRender或Graphics.DrawMesh的方式,材質有勾Enable GPU Instancing來渲染,後者是透過手動在MonoBehavior裡呼叫Graphics.DrawMeshInstanced來渲染,
相關細節可以參考我這一篇:
Unity Batching與GPU instance效能分析
而不管是用那種方式,view frustum culling處理的部份都不是很理想,皆會造成送進去的triangles數量過多,如果是像草這種quad,就還好,但是像這種幾百幾千面的物件性能就不行…

這裡針對俯視視角進行相關的culling處理,所以採取了斜視口剔除(Oblique Bound Culling)的做法,相關細節可以參考我這一篇:
使用斜視口剔除(Oblique Bound Culling)來做大量物件剔除

雖然使用page切割已經達到大量剔除的目標,但是物件數巨量的話,這樣的剔除的結果還是太多,但如果直接用frustum對這些物件進行檢測的話,數量太多,會造成CPU bounds,所以這裡採用了Unity的Job System的方案,使用多執行緒來優化這部份。

2019年10月22日 星期二

簡單又易實現的Merge Shader

一般的情況,如果山脈拆開來獨立做,不用Terrain拉高低,就會產生硬的邊緣,用簡單Merge Shader可以解決這個問題,廢話不多說,流程如下:

  1. 渲染地表,並將結果拷貝到一張渲染貼圖上。
  2. 在渲染物件的時候,依照高度資訊,並參考這張Screen Space的渲染貼圖,來進行混色處理
PS:如果不是平地的話,就需要目前的深度貼圖,來取得高度資訊做比較,平地的話,一個固定的height值就OK。
結果如下:

2019年9月27日 星期五

使用斜視口剔除(Oblique Bound Culling)來做大量物件剔除

策略類的遊戲,視角通常是俯視的角度,所以很多都會使用九宮格的Page Grid來做大量的物件剔除,但像萬國覺醒這種無極縮放的遊戲,就很難固定是九格了,所以這裡我們用Oblique Bound來做動態page剔除(而非固定的九格)。

什麼是Oblique Bound,如下圖…





這樣我們不管拉近,拉遠,都會有一個比較適合的page column row index,也可以享受拜訪page不用做額外碰撞檢查的好處。

相關影片如下:

2019年7月3日 星期三

關於Unity Project Decal的做法分析

Project Decal蠻常用來處理彈孔、魔法陣(AE範圍)、圓圓影…等貼花效果,在Unity下目前提供的方案是Projector,但目前這個方式使用MultiPass的做法,會造成畫二次(三角面暴增)及打斷Batching的問題。

未使用Projector的狀況:


使用Projector的狀況:



很明顯的,使用過Projector後,Draw Batches從39提升到56,而Tris從29.3K提升到42.1K

有沒有其他的做法呢?目前主流的做法是用一個Volume範圍(通常是用Box)加上深度貼圖來處理,在腳本運行的時候,時時計算這個投射矩陣,並帶入Shader,之後利用深度貼圖來計算投影的UV,最後只要把這個Volumle畫就來就行。其實這個概念跟Unity的Original Projector是差不多的,差別是在前者利用深度圖貼來計算投影UV,而後者則是利用多畫一次自己,再用自己的位置資料來當深度。

使用Volume Projector的狀況如下:


結果Draw Batches是40,只有增加1,而Tris只有多畫一個Box,所以看不出任何提升。

另外還有一種做法,是Polygon Projector,他是採用碰撞處理的方式,動態取得鄰近的三角面,並攤提UV的做法,這樣的方式最大的好處是比較不會發生投影超過二次以上的狀況(比方上下疊層),但缺點就是要算碰撞,如果碰撞引擎性能很好的話,其實效能也不錯,這是我當時在Ogre+Bullet引擎的實作,目前還沒實作出Unity的版本,相關影片如下…

2019年5月28日 星期二

如何使用Flow Map quads來實現互動水波

由於之前實現的水波系統,無法實現在無限大的水體,而且覺得目前美術使用特效的方式來處理航行特效,感覺非常生硬,完全跟水沒有互動感。最近看了flow map蠻流行的,看看有沒有實現的可能性,於是開啟了如何使用Flow Map quads來實現互動水波之路。

以下是大概的執行流程:
  1. 使用GPUInstance或Partilce system,時時噴射noise animation flow map quads,並處理好相關的alpha消失及scale漸漸變大的部份。
  2. 渲染到一張screen space的flow map。
  3. 在water渲染時,參考flow map,並依照flow方向及alpha權重,影響normal及泡沫的比重
結果如下: