[遊戲特效魔法師]Image Effect

Chris Lin
5 min readJun 15, 2019

--

Post-Processing(後期處理)是在遊戲製作中將原本透過攝影機渲染過後的畫面,經過特製的影像處理Shader計算後,進而改變原本影像質感的一種方法。像是景深(DOF)、動態模糊(Motion Blur)、光暈(Bloom)、濾鏡(Color Grading)等效果都是經過Post-Processing的加工,讓影像品質更加出色。

Unity本身就有推出Post-Processing Stack,提供許多常用的後期特效。基本上已經很夠用了,但其實還是會有許多效果必須自己撰寫。這篇文章就在教大家如何自己寫一個Image Effect。

早期也有一套Legacy Image Effect,不過年代久遠,官方建議使用新版的Post-Processing Stack。

有關Post-Processing Stack的使用會在另一篇文章說明

撰寫客製化的Image Effect有兩個方法,一個是透過OnRenderImage和搭配Shader,另一個是直接延伸Post-Processing Stack和搭配Shader來擴充。Post-Processing Stack已經在另一篇文章說過了,以下說明透過OnRenderImage的方式。

透過OnRenderImage

要透過OnRenderImage來實做後期特效,有幾個重點如下

OnRenderImage 不支援SRP

在Unity的SRP渲染系統下不支援OnRenderImage的方式來做全畫面的著色處理。所以如果你是使用LWRP、HDRP或是自己客製化SRP都無法使用,必須透過Post-Processing Stack擴充。

在2019的版本之後HDRP的後製效果必須透過Volume渲染系統

在Project View建立一個Image Effect Shader

在Project View上透過Create/Shader/Image Effect Shader來建立一個預設好的全畫面著色器腳本。

  • 預設一個_MainTex貼圖參數
    _MainTex一定要存在並且不能變更名稱,Unity會自動將目前Camera所渲染的畫面當作Source Texture傳入到_MainTex,提供給Image Effect來計算影像處理的依據。
  • Vertex Shader不需要變動
    基本上Image Effect都是對全畫面做處理,不太需要重新定義投影轉換的方式,除非你有特殊需求。Unity會自動建立一個面片(Quad)覆蓋在畫面上,讓接下來Fragment Shader重新將計算好的像素資料覆蓋在全畫面上,產生出新的影像內容。
  • 將你要處理的影像演算法寫在Fragment Shader裡

撰寫一個C#腳本並覆寫OnRenderImage

在Procject View上新建一個C#程式腳本,並且在程式碼裡加上OnRenderImage這個函式。

void OnRenderImage(RenderTexture src, RenderTexture dest)

OnRenderImage會傳入兩個參數

  • src指的是目前Camera所渲染的Render Buffer,將這個參數當作要處理的影像資料(貼圖)傳入。Unity會自動將src傳入到Image Effect Shader的_MainTex這個參數。
  • dest指的是最後要輸出的Render Buffer,Unity會自動產生一塊影像記憶體,將Image Effect Shader所渲染的像素紀錄在dest上

其他重點

  • 建立材質球
    要讓Image Effect發揮效果,首先就是要建立一個專屬的材質球
if (m_Material == null)
{
m_Material = new Material(Shader.Find("Image Effect/DOF"));
m_Material.hideFlags = HideFlags.DontSave;
}
  • 參數更新
    將參數傳入材質球,更新渲染效果
m_Material.SetFloat("_SampleDist", m_Dist);
m_Material.SetFloat("_SampleStrength", m_Strength);
m_Material.SetVector("_Center", new Vector4(m_Center.x, m_Center.y, 0.0f, 0.0f));
  • 呼叫Graphics.Blit
    傳入src、dest與材質球,進行全畫面渲染。
  • 在編輯模式執行
    為了方便在開發中能夠快速地反應出畫面效果,記得加上[ExecuteInEditMode]讓程式在編輯器模式下直接運行

將撰寫好的C#腳本掛載到Camera上

Image Effect的執行必須透過Camera這個Component來運作。Camera在運行渲染的工作之後,會呼叫OnRenderImage。如果Camera所存在的GameObject上有掛載撰寫有OnRenderImage的腳本,就會被觸發。

附上Radial Blur的範例

--

--

Chris Lin

一位遊戲開發者,熱愛遊戲、籃球、健身與遊戲程式設計 / A game developer, love in play game, basketball, fitness and programming for game.