1、什么是屏幕特效
我們這里講的屏幕特效技術,指的是在渲染完整個場景后得到的屏幕圖象的基礎上,再對這個屏幕圖像做一系列處理,實現出屏幕特效,使用這種技術可以為屏幕畫面增添各種風格的藝術效果,比如泛光、景深、模糊等等。
2、unity實現屏幕特效的原理
如上所述,要實現屏幕特效,首先要抓取渲染完整個場景得到的屏幕圖像,在unity中,提供了OnRenderImage函數,方便我們進行這樣的操作。它的聲明如下:MonoBehaviour.OnRenderImage(RenderTexture src,RenderTexture dest);unity會把當前渲染得到的圖像存儲在第一個參數對應的渲染紋理中,通過自定義的一系列操作后,得到目標渲染紋理(第二個參數中的渲染紋理),目標渲染紋理會最終顯示在屏幕上。在OnRenderImage函數中,使用Graphics.Blit函數來對渲染紋理進行處理。這里我們做一個可以改變畫面亮度、飽和度、以及對比度的簡單屏幕特效。
3、C#腳本實現
//////////////////////////////////////////////////////////////////// // _ooOoo_ // // o8888888o // // 88" . "88 // // (| ^_^ |) // // O\ = /O // // ____/`---'\____ // // .' \\| |// `. // // / \\||| : |||// \ // // / _||||| -:- |||||- \ // // | | \\\ - /// | | // // | \_| ''\---/'' | | // // \ .-\__ `-` ___/-. / // // ___`. .' /--.--\ `. . ___ // // ."" '< `.___\_<|>_/___.' >'"". // // | | : `- \`.;`\ _ /`;.`/ - ` : | | // // \ \ `-. \_ __\ /__ _/ .-` / / // // ========`-.____`-.___\_____/___.-`____.-'======== // // `=---=' // // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // // 佛祖保佑 永無BUG // //////////////////////////////////////////////////////////////////// using System.Collections; using System.Collections.Generic; using UnityEngine; [ExecuteInEditMode] [RequireComponent(typeof(Camera))] public class ScreenEffect : MonoBehaviour { public Shader effectShader; private Material effectMaterial; public Material EffectMaterial { get { effectMaterial = CreateMaterial(effectShader, effectMaterial); return effectMaterial; } } [Range(0.0f, 3.0f)] public float brightness = 1.0f; //亮度 [Range(0.0f, 3.0f)] public float saturation = 1.0f; //飽和度 [Range(0.0f, 3.0f)] public float contrast = 1.0f; //對比度 void OnRenderImage(RenderTexture src, RenderTexture dest) { if (EffectMaterial != null) { EffectMaterial.SetFloat("_Brightness", brightness); EffectMaterial.SetFloat("_Saturation", saturation); EffectMaterial.SetFloat("_Contrast", contrast); //對渲染紋理進行處理 Graphics.Blit(src, dest, EffectMaterial); } else { Graphics.Blit(src, dest); } } private void Start() { bool isSupported = CheckSupport(); if (isSupported == false) { this.enabled = false; } } // 檢測當前平台是否支持屏幕特效 private bool CheckSupport() { if (SystemInfo.supportsImageEffects == false || SystemInfo.supportsRenderTextures == false) { Debug.LogWarning("當前平台不支持!"); return false; } return true; } // 創建材質 private Material CreateMaterial(Shader shader, Material material) { if (shader == null) { return null; } if (shader.isSupported && material && material.shader == shader) return material; if (!shader.isSupported) { return null; } else { material = new Material(shader); material.hideFlags = HideFlags.DontSave; if (material) return material; else return null; } } }
4、Shader實現
Shader "yzpShader/ScreenEffect" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} //需要處理的渲染紋理 _Brightness ("Brightness", Float) = 1 //亮度 _Saturation("Saturation", Float) = 1 //飽和度 _Contrast("Contrast", Float) = 1 //對比度 } SubShader { Pass { ZTest Always Cull Off ZWrite Off CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" sampler2D _MainTex; half _Brightness; half _Saturation; half _Contrast; struct v2f { float4 pos : SV_POSITION; half2 uv: TEXCOORD0; }; v2f vert(appdata_img v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.uv = v.texcoord; return o; } fixed4 frag(v2f i) : SV_Target { fixed4 renderTex = tex2D(_MainTex, i.uv); // 計算亮度改變后的顏色 fixed3 finalColor = renderTex.rgb * _Brightness; // 計算飽和度改變后的顏色 fixed luminance = 0.2125 * renderTex.r + 0.7154 * renderTex.g + 0.0721 * renderTex.b; fixed3 luminanceColor = fixed3(luminance, luminance, luminance); finalColor = lerp(luminanceColor, finalColor, _Saturation); // 計算對比度改變后的顏色 fixed3 avgColor = fixed3(0.5, 0.5, 0.5); finalColor = lerp(avgColor, finalColor, _Contrast); return fixed4(finalColor, renderTex.a); } ENDCG } } Fallback Off }
5、測試結果
首先將C#腳本掛在場景相機上,並將上面寫好的shader拖拽到ScreenEffect腳本的effectShader上,修改該腳本的brightness、saturation、contrast值,可以得出下面這樣的效果: