
Unity在新的渲染管線SRP系統下,已經不再支援使用OnRenderImage這個函式來渲染Image Effect。必須走Post-Processing Stack V2系統(LWRP)和Volume系統(HDRP)才能夠運行Image Effect。
這篇文章主要是跟大家介紹如何在LWRP渲染管線下,用Post-Processing Stack V2來客製化自己的Image Effect。在Build-in渲染管線下使用Post-Processing Stack V2客製化Image Effect也是使用相同的方式喔。
(HDRP的部份等我研究完再分享)
上面的網址是Unity官方GitHub上的說明連結,有興趣也可以看看。
C#腳本
using UnityEngine.Rendering.PostProcessing;

新增一個繼承於PostProcessingSettings的class

由於Setting物件必須是可序列化,這樣才可以透過Inspector設定參數,在class之前加上[Serializable]。而該腳本的當案名稱也必須跟有加上[Serializable]屬性的class名稱一致,如此才能透過反射機制轉型。
在新增的Setting class裡宣告要控制的變數,變數的宣告必須符合Parameter形式,例如原本會宣告為float型別的變數,要宣告為FloatParameter。

- FloatParameter -> float
- ColorParameter -> Color
- Vector4Parameter -> Vector4
- TextureParameter -> Texture
新增一個繼承於PostProcessEffectRenderer的class,PostProcessEffectRenderer是一個樣板類別,傳入的型別就是上面所寫的Setting class。

為了要讓Post-Processing Stack V2知道如何引入客製化的Image Effect,在Setting class前加上[PostProcess]屬性。

[PostProcess]屬性共有四個參數可以設定
- 第一個參數是指定實際上運行Shader的class,該class必須繼承於PostProcessEffectRenderer
- 第二個參數有三個屬性可以設定
BeforeTransparent:要運行的Image Effect會在渲染透明物件之前執行,也就是畫面的效果只會影響到不透明物件。
BeforeStack:會在Post-Processing Stack V2預設所有內建的效果執行前優先運行。
AfterStack:會在Post-Processing Stack V2預設所有內建的效果執行後和FXAA和Dithering執行前之間運行。 - 第三個參數是設定新增Image Effect到Profile堆疊裡的選單路徑。
- 第四個參數是選擇性的,是設定為是否要在Scene View上預覽效果,預設為true。
最後就是撰寫PostProcessEffectRenderer的Render函式,Post-Processing Stack V2會每個Frame執行這個函式,可以將這個函式當作是Update來更新所有的參數。

- 首先就是要先把Shader給Load進來
- 透過PropertySheet來設定Shader裡的參數,設定方式跟設定Material一樣
- 最後就是透過command.BlitFullscreenTriangle來繪製全畫面,繪製的原理就會建立一個全畫面投影的面片(Quad),然後透過Shader將畫面逐一重新填色。
Shader Code
LWRP要撰寫Image Effect的特效,在2019之前的版本,可以透過由Brahim Hadriche所寫的ImageEffectGraph,這樣就可以用Shader Graph來編輯Shader。
在2019之後用ImageEffectGraph會有很多錯誤,基本上是不太能用(期待之後Brahim Hadriche大大可以修正)。
如果不使用Shader Graph來編輯的畫,Post-Processing Stack V2不能使用Unity預設的Image Effect Shader來渲染,必須撰寫HLSL的Shader才能正常執行。
希望Shader Graph能夠盡快支援Image Effect的編輯。

- Shader Code要放在HLSLINCLUDE / ENDHLSL與HLSLPROGRAM / ENDHLSL之間。
- 在進行繪圖時會把傳入的Source Texture直接傳到Shader裡的_MainTex貼圖參數,所以Shader裡一定要宣告_MainTex。
- 通常只要撰寫Fragment Shader,Vertex Shader可以用Unity預設的或是自己寫一個簡單的投影轉換。
v2f vert(appdata_img in)
{
v2f o;
o.pos = mul(UNITY_MARTIX_MVP, in.vertex);
o.uv = in.texcoord;
return o;
}
- 通常不進行ZTest與ZWrite。
- 使用Unity已經定義好的macro來進行運算,這樣會有比較好的跨平台支持。
客製化Inspector
- 引用UnityEngine.Renderer.PostProcessing與UnityEditor.Renderer.PostProcessing

- 加上[PostProcessEditor]屬性,定義是屬於哪個class的擴充編輯

- 繼承PostProcessEffectEditor,類別名稱宣告為擴充類別名稱 + Editor

- 利用SerializedParameterOverride宣告對應的變數

- 在OnEnable配對原始的屬性變數

- 在OnInspectorGUI顯示客製化欄位

以下是範例