Unity Shader 屏幕後效果——顏色校訂

屏幕後效果指的是,當前整個場景圖已經渲染完成輸出到屏幕後,再對輸出的屏幕圖像進行的操做。app

 

在Unity中,通常過程一般是:ide

1.創建用於處理效果的shader和臨時材質,給shader腳本傳遞須要控制的參數和變量函數

2.利用OnRenderImage函數抓取當前屏幕渲染紋理測試

OnRenderImage(RenderTexture source, RenderTexture destination){  }ui

第一個參數爲處理前紋理,第二個爲最終顯示紋理spa

3.在OnRenderImage函數中調用Graphics.Blit方法對抓取的紋理進行具體的後期操做code

Graphics.Blit(source, destination, material,-1);blog

material爲須要處理的材質,-1爲參數pass的默認值,表示對shader中全部的pass依次調用,這裏也能夠省略繼承

 

爲此,首先能夠提早創建一個基類ScreenEffectBase,主要用於檢查Shader並建立臨時材質:ip

腳本以下:

 1 using UnityEngine;
 2 
 3 [ExecuteInEditMode]
 4 //屏幕後處理效果主要是針對攝像機進行操做,須要綁定攝像機
 5 [RequireComponent(typeof(Camera))]
 6 public class ScreenEffectBase : MonoBehaviour
 7 {
 8     public Shader shader;
 9     private Material material;
10     protected Material Material
11     {
12         get
13         {
14             material = CheckShaderAndCreatMat(shader, material);
15             return material;
16         }
17     }
18 
19     //用於檢查並建立臨時材質
20     private Material CheckShaderAndCreatMat(Shader shader, Material material)
21     {
22         Material nullMat = null;
23         if (shader != null)
24         {
25             if (shader.isSupported)
26             {
27                 if (material && material.shader == shader){ }
28                 else
29                 {
30                     material = new Material(shader){ hideFlags = HideFlags.DontSave };
31                 }
32                 return material;
33             }
34         }
35         return nullMat;
36     }
37 }

以後建立的屏幕後處理效果的控制腳本均可以繼承自該基類,例如咱們建立關於基本顏色校訂的控制腳本:

 1 using UnityEngine;
 2 
 3 public class ColorCorrectionCtrl : ScreenEffectBase
 4 {
 5     private const string _Brightness = "_Brightness";
 6     private const string _Saturation = "_Saturation";
 7     private const string _Contrast = "_Contrast";
 8 
 9     [Range(0, 3)]
10     public float brightness = 1.0f;
11     [Range(0, 3)]
12     public float saturation = 1.0f;
13     [Range(0, 3)]
14     public float contrast = 1.0f;
15 
16     private void OnRenderImage(RenderTexture source, RenderTexture destination)
17     {
18         if (Material!=null)
19         {
20             Material.SetFloat(_Brightness, brightness);
21             Material.SetFloat(_Saturation, saturation);
22             Material.SetFloat(_Contrast, contrast);
23 
24             Graphics.Blit(source, destination, Material);
25         }
26         else
27             Graphics.Blit(source, destination);
28     }
29 }

其中,brightness,saturation,contrast分別爲調整參數——亮度,飽和度和對比度,_Brightness,_Saturation,_Contrast爲以後對應的shader中須要相應定義的屬性參數。

這裏利用構建的材質Material對shader的屬性賦值並調用Graphics.Blit進行屏幕後效果的處理。

 

具體實現顏色校訂的shader以下:

 1 Shader "MyUnlit/ColorCorrection"
 2 {
 3     Properties
 4     {
 5         //這裏的參數主要用於展現在材質面板中進行調節,但由於此次是臨時建立的材質,參數都已經放在了C#腳本中調整,所以相對應的參數均可以省略
 6         _MainTex ("Texture", 2D) = "white" {}
 7     }
 8     SubShader
 9     {
10         Tags { "RenderType"="Opaque" }
11 
12         Pass
13         {
14             //OnRenderImage的調用可能會發生在渲染透明物體以前,爲了避免影響以後透明物體的渲染,須要:開啓深度測試+雙面渲染+關閉深度寫入
15             ZTest always
16             Cull off
17             ZWrite off
18 
19             CGPROGRAM
20             #pragma vertex vert
21             #pragma fragment frag
22             #pragma multi_compile_fog
23 
24             #include "UnityCG.cginc"
25 
26             struct appdata
27             {
28                 float4 vertex : POSITION;
29                 float2 uv : TEXCOORD0;
30             };
31 
32             struct v2f
33             {
34                 float2 uv : TEXCOORD0;
35                 UNITY_FOG_COORDS(1)
36                 float4 vertex : SV_POSITION;
37             };
38 
39             sampler2D _MainTex;
40             half _Brightness;
41             half _Saturation;
42             half _Contrast;
43 
44             v2f vert (appdata v)
45             {
46                 v2f o;
47                 o.vertex = UnityObjectToClipPos(v.vertex);
48                 //由於是臨時建立的材質,這裏不須要對紋理進行任何變換操做(無可操做的材質面板),直接傳遞便可,_MainTex_ST也不須要定義
49                 o.uv = v.uv;
50                 UNITY_TRANSFER_FOG(o,o.vertex);
51                 return o;
52             }
53 
54             fixed4 frag (v2f i) : SV_Target
55             {
56                 fixed4 col = tex2D(_MainTex, i.uv);
57 
58                 //亮度計算直接疊加
59                 fixed3 color = col.rgb*_Brightness;
60 
61                 //飽和度和灰度有關,先計算最低灰度係數下的圖像,隨後對原始的圖像進行插值操做
62                 fixed3 gray = fixed3(0.2125, 0.7154, 0.0721);
63                 //點積獲得最低灰度值,構成最低灰度圖像
64                 fixed minGray = dot(gray, col.rgb);
65                 fixed3 grayColor = fixed3(minGray, minGray, minGray);
66                 //對灰度圖像和原始圖像插值操做以獲得最終係數的顯示圖像
67                 color = lerp(grayColor, color, _Saturation);
68 
69                 //對比度效果相似,先計算最低對比度圖像,即(0.5,0.5,0.5),隨後插值操做
70                 fixed3 minContrast = fixed3(0.5, 0.5, 0.5);
71                 color = lerp(minContrast, color, _Contrast);
72 
73                 //獲得全部處理完成後的圖像顏色,但alpha保持不變
74                 fixed4 finColor = fixed4(color, col.a);
75 
76                 UNITY_APPLY_FOG(i.fogCoord, finColor);
77                 return finColor;
78             }
79             ENDCG
80         }
81     }
82     //關閉回調
83     fallback off
84 }

效果以下(隨便調的不用在乎~):

相關文章
相關標籤/搜索