發表文章

目前顯示的是有「Unity」標籤的文章

Rain Drop

圖片
  下雨效果分析,可以分成2個部分。一個是平面的雨滴效果,一個是垂直側面的流水效果。 先來看平面的雨滴效果。可以用類似積雪的方式,找出模型法線向上的部分,再搭配下雨的序列圖,組合出水平面的雨滴效果。 再來是垂直側面的部分。跟垂直類似,遮罩採用模型法線X與Z方向的遮罩,配合擾動UV流動的效果製作側邊的流水效果。 最後再將效果合入shader當中PBR的光照計算即可。 References: https://www.youtube.com/watch?v=9JkG-orTQO8

CurveWorld

圖片
  這次來實現一下地平線彎曲的效果。有看過 Switch 的<動物森友會>的應該都有看過場景的遠景地方會彎曲的效果。 要實現的方式可以從 Shader vertex 上做頂點的彎曲。詳細的做法可以參考 HORIZON BEND 的 PDF 文章。 這邊就簡要的放上核心的曲面部分,基本上就是先將模型轉換為世界座標,再去製作彎曲效果,最後再轉回模型的本地座標。 如此一來就可以達到模型彎曲的效果。由於是在vertex製作彎曲,因此模型的面數也是會影響到彎曲後的效果。  最後就是讓地板循環位移,可以達到攝影機跟人物不動,而視覺有前進的效果。 References: https://battlehub.net/HorizonBend/HB.pdf https://unity-chan.com/download/releaseNote.php?id=SDUnityChan&lang=en

TextmeshPro-Gradient

圖片
這次來寫一篇關於 TextmeshPro 的擴展應用。有用文字系統的夥伴,相信一定對於 TextmeshPro 不陌生。由於它的多樣性文字效果,使得他幾乎專案當中是必備的存在。 然而 TextmeshPro 默認的漸層模式卻也是稍有侷限,只能接受上下 2種 不同得顏色的漸變效果,有時候不見得能夠符合需求。 因此這次則對漸層的方面做出擴展,來讓 TextmeshPro 能更支援更多的顏色漸變。 從默認的漸變模式的Shader可以得知,由於默認的漸變是藉由 頂點色染色 的緣故,因此對於一片面來說只有4個頂點,所以最多只能做到 上下 或是 左右 的漸變變化。 對此則可以運用給予漸層貼圖的方式讓它的漸變能支援更多的顏色變化。以下是使用 Gradient 動態產生建成貼圖。 Texture2D GenerateTextureFromGradient (Gradient gradient, int width = 64, int height =1 ) {             Texture2D texture = new Texture2D(width, height, TextureFormat.RGBA32, false);             for (int y = 0; y < height; y++)                 {                 for (int x = 0; x < width; x++)                     {                     float t = (float)x / (width - 1);                     Color color = gradient.Evaluate(t);                     texture.SetPixel(x, y, color);                 }             }             texture.wrapMode = TextureWrapMode.Clamp;             texture.Apply();             return texture; } 再來,我們可以利用頂點色作為UV的辦法將貼圖平鋪到文字上面。由於已經有

Stencil Portal Effect

圖片
前些日子有個需要傳送門的效果,這裡就寫一下  Stencil 的功能。 從官網的解釋 : 模板緩衝區為幀緩衝區中的每個像素儲存一個 8 位元整數值。在為給定像素執行片元著色器之前,GPU 可以將模板緩衝區中的當前值與給定參考值進行比較。這稱為模板測試。如果模板測試通過,則 GPU 會執行深度測試。如果模板測試失敗,則 GPU 會跳過對該像素的其餘處理。這意味著可以使用模板緩衝區作為遮罩來告知 GPU 要繪製的像素以及要丟棄的像素。 大致上有個了解。就是將 ref 中的 value 與 buffer 中的 value 進行比較,來決定繪製像素的一種方式。 主要的配合方式可以如下 :  如此便可以製作出物件通過 傳送門 的效果。 附帶一提,Stencil 也可以用在 人物遮擋 的顯示效果上面。 References: https://docs.unity3d.com/cn/current/Manual/SL-Stencil.html https://www.youtube.com/watch?v=toQIuCtk2pI https://www.youtube.com/watch?v=SySnHIhiVgM

Overdraw

圖片
  這次來看一下有關性 能方面的大殺手 Overdraw 。 相信許多特效的夥伴對這名詞一定不陌生。 Overdraw可以解釋為,在一幀中, 同一個像素的多次(重複)的繪製 。而畫面當中大量的 Overdraw 則是手機/移動平台上的性能大忌。會很嚴重的影響到 FPS 。 目前市面上的 手機/移動平台是 採用 TBR(tile-based rendering) 的渲染方式,因此在 CPU 到 GPU 之間需要傳輸大量的數據,而大量的 Overdraw 則會導致 頻寬消耗 ,造成渲染性能(FPS)下降。 再來從渲染管線來看,手機/移動平台的渲染管線大都是 Forward Rander (向前渲染) 的原因,因此容易造成大量 Overdraw 的因素大部分會產生在 Transparent 跟 UI 層級 以及 P ost Processing (後處理) 上面。 而為了避免 Overdraw 造成的性能浪費,在素材製作上製作也必須有些基本的概念。 1. 特效 的效果則有很大部分都會藉由粒子系統的效果產生大量的 Mesh,從而導致大量的疊加情況。需要限制噴發模型數量,來減少疊加的狀況。 2. UI 的製作上也避免過多的層級疊加。 3.P ost Processing (後處理) 避免使用過多的後處理。由於每一種後處理都是全屏幕的像素繪製。 最後性能檢測方面。我們可以用最值觀的 引擎內的 Overdraw 模式 來檢視。或是可以用 Render doc 來進行更仔細的幀 畫面分析。 Render doc 單場景大量粒子疊加Overdraw畫面 或是可以用 OverdrawMonitor 工具來觀察畫面 的 Overdraw 比例 。原則上再依畫面盡量能保持在 3.0 以內為最好。(1.0 即是每一項像素只繪製一次) References: https://zhuanlan.zhihu.com/p/350778355 https://www.youtube.com/watch?v=vJZcbscZ4-o https://github.com/Nordeus/Unite2017/tree/master/OverdrawMonitor

GPU Instancing & Boids

圖片
  GPU Instancing 是一項大量重複的物件繪製的時候一種優化的方式。原理是在 相同的3D模型 一次性渲染多次,利用GPU的並行處理能力,極大地減少了CPU和GPU之間的溝通成本,進而提高了渲染效率。 適用於大量重複的物件。對於不同的物件,還是需要進行單獨的渲染。其次,雖然GPU Instancing可以減少CPU和GPU之間的通信開銷,但如果物件數量不夠多,可能無法發揮出其優勢。因此,在使用 GPU Instancing 時,需要根據具體的場景和需求進行適當的優化和調整。 這邊使用了 群鳥移動 Boids 的演算法來演示在大量物件情形中配合 GPU Instancing 的製作。 群鳥移動 Boids 是一種模擬大量物體之間運動的一種算法,有興趣的可以再爬文了解,這邊就不詳細說明。從畫面看,魚群體會在已經限制的範圍內做模擬的群體運動,同時個體之間也會保有間距不重複。 而在GPU Instancing的 魚群當中,我們也可以做出個別的差異。例如 顏色/頂點位移 的偏移。             UNITY_INSTANCING_BUFFER_START(Props)                 UNITY_DEFINE_INSTANCED_PROP(float4, _MaskColor)                 UNITY_DEFINE_INSTANCED_PROP(float, _VertOffset)             UNITY_INSTANCING_BUFFER_END(Props) 當中 _MaskColor 可以讓 GPU Instancing 的 Shader 當中設定顏色,_VertOffset  則是設定頂點運動的偏移值。 在頂點運動上的方式:                     fixed voffset = UNITY_ACCESS_INSTANCED_PROP(Props, _VertOffset);                 float4 offset = float4(0,0,0,0);                 offset.y = _speedRange0 * sin(_Time.y * _speedRange1 + voffset) * mask * mask2 ;          

CommandBuffers

圖片
  在2月29日來發一篇也挺有意思的XD。這篇來寫一下默認管線( Built-in Render Pipeline )當中的  CommandBuffers 功能 。 默認管線當中,渲染的順序是固定的模式,不容易調整。大部分情況下就要按照, 不透明/天空球/透明/後處理/UI 等的渲染順序來渲染屏幕的物件。而 CommandBuffers 則是用來自訂部分渲染的方式來擴展 Unity 的默認管線。 我們可以對要渲染的攝影機增加  CameraEvent 的方式來添加希望增加的渲染內容。例如:希望在 不透明(Opaque) 渲染之後希望另外增加額外的渲染則可以用 CameraEvent.AfterForwardOpaque 的方添加到攝影機上面 ( Camera. AddCommandBuffer ( CameraEvent, CommandBuffer)  ) 。 同時記得不使用時需要從攝影機上移除 ( Camera. RemoveCommandBuffer ( CameraEvent, CommandBuffer) ) 。 從這個魔法球的效果來說,會希望內部帶有扭曲的情形,因此我們可以如同上面講一樣,在 不透明(Opaque) 之後添加 CommandBuffer 讓不透明(Opaque)的部分製作全屏幕的扭曲效果(Distort),再與之後的球體物件 半透明(Transparent) 做疊加處理,來達到內部扭曲&染色的特殊表現。 球體貼牆面會有的邊緣效果是則是利用了深度圖(  _CameraDepthTexture ) 取得的 邊緣(Edge)效果。 設定  CommandBuffer C# 的部分 :  private void RendererCommandBuffer(ref CommandBuffer buf, ref Material mat) { buf.name = "[CommandBuffersEffect]"; int screenCopyID = Shader.PropertyToID("_ScreenCopyTexture"); buf.GetTemporaryRT(screenCopyID, -1, -1, 0, FilterMode.Bilinear);

Vertex Animation Texture

圖片
新年新的開始,祝大家都心想事成,一切順心! 今年也期許自己能夠繼續保持記錄部落格。 VAT 的全名是 Vertex Animation Texture ,是一種用來實現模型動畫效果的技術。 其基本原理是透過記錄模型頂點的變化訊息,並將這些資訊預先烘培( bake )到紋理中,然後在頂點著色器中讀取烘培好的紋理,從而實現模擬物理動畫等效果。 相較於即時運算實體的動畫效果,VAT是一種較為輕量級的解決方案,更 適用於行動裝置 等要較為限制性能的地方。其主要優勢之一是在運行時不需要進行複雜的物理計算,而是直接讀取烘培好的紋理,因此對手機設備性能更友善。 由於是採用烘培的方式擷取動態,因此也能做到回播的效果。重複撥放。 然而,使用VAT也帶來了一些特定的考慮和限制。由於需要記錄模型的位移和旋轉資訊到紋理中,會導致需要額外的儲存空間,並且這些位移/旋轉紋理通常不能被壓縮,以確保動畫效果的準確性和品質。 因此,相對於其他動畫技術,VAT可能會佔用更多的記憶體。需要在製作貼圖時仔細考量動畫時間長度降量減少貼圖使用,來平衡效能和效果。 下面由這張圖來大致示意一下貼圖以及模型的關係: 這邊就結合了大規模渲染必備的 GPU Instancing 方式來呈現大量石頭碎裂的的效果。(碎裂後的底圖則是借用ICON~) 附帶一提API: Graphics.DrawMeshInstanced 可以換成 Graphics.RenderMeshInstanced 可以直接使用 NativeArray ,讓往後接到 JobSystem 可以再方便一些(雖然 RenderMeshInstanced 功能感覺也還沒寫完整) References: https://storyprogramming.com/2019/09/18/shader-graph-rigid-body-animation-using-vertex-animation-textures/

CustomBloom

圖片
對於美術朋友來說,後製的Bloom泛光需求基本上是標配的存在。而特效美術而言,也常有會希望能有限制範圍的泛光效果,而不是全屏幕的Bloom泛光。此時內建的後製Bloom就無法達成這類需求,所以就須要自己下去客製化Bloom(CustomBloom)。 這次也是基於Unity 內建渲染管線 (Built-in Render Pipeline)上來實現。在CustomBloom上可以為2個部分。 第1部分是我們需要知道特定的物件(特效)的範圍,因此可以在該效果的Shader之下再多加上一個 Pass 用來繪製遮罩部分。 第2部分則是將遮罩部分交由後製的CustomBloom的後制效果,走標準的流程( 高斯模糊 )處理,來達到特定範圍的泛光效果。 References: https://assetstore.unity.com/packages/3d/environments/3d-scifi-kit-starter-kit-92152

FBXAnimationEditor

圖片
上傳到  Unity Asset Store 的工具也有好些日子,這陣子工具終於過審查上架了。這邊就來紀錄一下在上傳準備過程中碰到的一些事情以及介紹一下這個工具。 為了能夠上傳  Unity Asset Store 商店,首先最重要的是必須有個 Unity 的帳號。再來只需要按照官方的影片將帳號內所需要的部分填寫清楚。 How to Publish on the Unity Asset Store 等到帳號的內容準備完成之後,再來就是要準備要上傳的品項了。這時還需要去 Unity Asset Store 當中加入一個套件  Asset Store Publishing Tools 到自己的 Unity Package 當中。 再來就是用 Asset Store Publishing Tools 將商品上傳到自己的  Unity 帳號當中等待官方審核。而等待過審的時間保守來看估計要 一個多月 以上的時間才能通過。而審查後也會回覆你的品項是否通過,或是條件缺少要補圖補資料等,而我就因為宣傳圖不符合規定而被退了2次。1次是因為宣傳圖的尺寸不符,而另1次則是宣傳圖上的文字訊息過多。(當成說明文件在製作了...)而這2次往返的回覆則是挺快的,隔日就收到了通知。成功過審之後則會直接上架在 Unity Asset Store 商店當中。 FBXAnimationEditor 接下來是輪到 FBXAnimationEditor 工具的介紹。這個工具主要是用於協助 動畫師 導入FBX 的 Animation 到 Unity 。用來節省動畫師的寶貴 時間 。 導入流程中 AnimationClip 依照時間長度裁切命名好並且設定是否循環,再將 AnimationClip 從 FBX 取出(複製出來)的過程。同時也支援將動作資訊存成 文字檔(txt) 來協助導入,用來加速這些繁瑣的導入過程,對於需要時常往返調整動作檔的 動畫師 而言可以大量節省這些重複的動作以及時間。詳細可以對照下面的 流程圖 以及 影片 觀看功能以及操作流程。以下歸納工具的好處以及優點: 1. 按照時間裁切動作檔 2. 動作檔命名 3. 設置動作是否循環 4. 支援文字檔(txt)導入/轉出已經編輯過的動作資訊 5. 節省重複性的導入步驟(時間)優化工作流程 流程圖 操作流程影片 最後再幫自己的插件推銷一下,可以

Depth Texture To World Position

圖片
  這篇來稍微實作一下深度圖的應用效果。 深度圖當中的數值介於 0~1 之間,精度通常為 32 or 16 bits,而且是非線性分佈,因此往往會需要再取到深度之後再轉一次成為線性的過程才比較方便後續使用。 這次的效果是在 Unity 內建渲染管線 (Built-in Render Pipeline)上製作。 一般來說要開啟深度圖可已在代碼當中加上 Camera.main.depthTextureMode = DepthTextureMode.Depth; 來讓攝影機取得深度圖資訊。 而這次是在 PostProcessing 效果上製作,因次需要在後製的 class 上加上 DepthTextureMode GetCameraFlags() 來讓攝影機開啟取得深度圖。 在開啟深度圖之後,所有的不透明物件(Opaque)都會多計算一次 Pass 來取得深度資訊(Z-Pre Pass)。如果有性能考量,須留意 DrawCall 是否增長過多。 如果是在URP環境,就可以使用 CopyDepth 的方式來取得不透明物件(Opaque)的深度圖。 再來便是在 void Render(PostProcessRenderContext context) 內執行相關的 shader 以及參數的設置。 由於我們希望從深度圖轉出世界座標,因此必須給予shader正確的 攝影機矩陣(Matrix4x4)資訊(傳遞目前的VP逆矩陣)。 最後則可以用後製shader得到的世界座標來做出貼地板的掃光效果。 References: https://ompuco.wordpress.com/2018/03/21/9/ https://www.jianshu.com/p/80a932d1f11e https://assetstore.unity.com/packages/3d/environments/landscapes/free-island-collection-104753 https://assetstore.unity.com/packages/3d/props/exterior/rock-and-boulders-2-6947

AvatarSystem

圖片
  關於Avatar系統,相信有經歷過 MMORPG 的夥伴一定不會陌生,也可以說得上是目前眾多遊戲的一種常規系統。 這邊就寫一下基礎的 Avatar 換裝功能流程。 首先要準備的是一組主骨架,也就是包含全部所有配件都有的骨架。 接下來是依照要拆分的部位,依序拆出來,例如: 頭 / 頭髮 /上半身 /下半身 等部位,而這些部位都必須有綁上跟主骨架相對應的骨架。 再來就是建立一組 Dictionary<string, Transform> 將主骨架的資訊紀錄在內,另一組 Dictionary<int, SkinnedMeshRenderer> 則紀錄上 部位 以及所包含的 SkinnedMeshRenderer 以便之後查找替換。 最後則是製作相對應的按鈕來替換 SkinnedMeshRenderer ,以及重新綁定 SkinnedMeshRenderer.bones 等重複的流程即可。 Avatar系統並不複雜,較為繁瑣的還是在資源的準備上。或是後續要加入的骨骼以及 Dynamic Bone 等細節處理上。 專案一開始要有良好的規範骨架名稱,才能讓 Avatar運作時能正確無誤的替換。 References:  https://assetstore.unity.com/packages/3d/characters/medieval-cartoon-warriors-90079

Custom PBR Shader

圖片
  基於物理的渲染(Physically Based Rendering),指的是基於真實的物理原理的 BRDF(雙向反射分佈函數) 模型 所構成的渲染方式。 PBR 的出現其實是為了能夠統一美術的製作流程而產生的一種標準化的生產方式,減少美術之間由於因為能力或者設備環境造成的差異的一種標準化模式。 或許有人會問,PBR在引擎內不是都已經有內建的,那為何還要花時間自己做一套呢? 這是由於 Unity 的標準化材質(PBR)會因為想讓使用者方便使用,所以做了很多的 Shader 開關,無形中會增加很多增加的 變體 (Variants) ,導致容量增加。 而且能客製化也代表了能夠更掌握視覺與性能部分,不會被引擎內建的PBR各種限制。增加了往後專案的可擴充性以及彈性。 關於解釋 PBR 相關的文章相信網路上的資源也是很多了,這裡對原理就不再多說明。只關注於如何實踐這部分。 對於 PBR 的 BRDF 一般可以分為4個項目。 分別為 : 直接光的 Diffuse + 直接光的 Specular + 間接光的 Diffuse  + 間接光 Specular  以下則為客製化的展示效果,以及不同引擎內客製化PBR的效果。由於是自己實現的PBR,因此可以更確保在不同引擎內有極為接近的渲染效果。使用的模型則是以前做的模型重裝騎士。

Using sampler states

圖片
記錄下一些寫 Shader 上的知識點。 由於在製作寫地板 Shader 的時候 ,時常會使用到 SplatTexture 配合多張貼圖(筆刷)的混合處理,因此會需要多張貼圖(筆刷)的採樣 (samplers) 但是在單個 Shader中 ,採樣器(samplers)則會有使用上的上限。(例如,Direct3D 11 允許在單個著色器中使用最多 128 個紋理,但最多只能使用 16 個採樣器。) 因此可以使用 Unity 提供的 Using sampler states ,來達到貼圖採樣器的共用來達到節省 採樣器 (samplers)的使用。而且多個採樣器(samplers)的使用也會造成運行上的下降。

Paint Demo

圖片
  Paint Demo 前些日子,幫朋友研究了下 POWERWASH SIMULATOR 這款遊戲的噴槍效果。 實現思路大致是: 1.在標準 PBR材質上加上一張RT的遮罩,讓其物件 髒汙部分與原本的材質做 Blend。 2.物件加上碰撞體 (MeshCollider) ,藉由 射線(Ray) 取得物件與滑鼠的座標,Set Material 到 Shader 內計算出繪製範圍。 3.最後再將範圍 Blit 到對應到 RT上。 由於是 RT的遮罩,所以模型的 UV是不能有共用的部分。 這邊就用以前製作的火炮作展示影片。

URP Render Underwater Transparent Objects

圖片
某天在圖學大佬的指導下,開始著手探究 URP 的渲染架構,在此記錄下一些知識點。 在一般的情況下Unity的渲染方式會依據 Shader 內的 Queue 標籤 順序渲染物件,所以在默認 狀況下,水的 Shader 是 Transparent 模式。但是這也會造成 其他 Transparent 的物件在水面下會無法顯示的情況。因此,我們可以對其渲染的機制順序做調整,來讓其餘的 Transparent 物件也能在水底下顯示。