using System.Collections; using System.Collections.Generic; using UnityEngine; [ExecuteInEditMode] [RequireComponent(typeof(Camera))] public class DepthOfFieldPostEffect : MonoBehaviour { public Material mat; [Range(0.0f, 100.0f)] public float focalDistance = 10.0f; [Range(0.0f, 100.0f)] public float nearBlurScale = 0.0f; [Range(0.0f, 1000.0f)] public float farBlurScale = 50.0f; //分辨率 public int downSample = 1; //採樣率 public int samplerScale = 1; private Camera mCam; public Camera Cam { get { if (mCam == null) { mCam = GetComponent(); } return mCam; } } private void OnEnable() { if(Cam != null) { Cam.depthTextureMode |= DepthTextureMode.Depth; } } private void OnDisable() { if(Cam != null) { Cam.depthTextureMode &= ~DepthTextureMode.Depth; } } // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } private void OnRenderImage(RenderTexture src, RenderTexture dest) { if(mat!=null) { //首先將我們設置的焦點限制在遠近裁剪面之間 Mathf.Clamp(focalDistance, Cam.nearClipPlane, Cam.farClipPlane); //申請兩塊RT,並且分辨率按照downSameple降低 RenderTexture temp1 = RenderTexture.GetTemporary(src.width >> downSample, src.height >> downSample, 0, src.format); RenderTexture temp2 = RenderTexture.GetTemporary(src.width >> downSample, src.height >> downSample, 0, src.format); //直接將場景圖拷貝到低分辨率的RT上達到降分辨率的效果 Graphics.Blit(src, temp1); //高斯模糊,兩次模糊,橫向縱向,使用pass0進行高斯模糊 mat.SetVector("_offsets", new Vector4(0, samplerScale, 0, 0)); Graphics.Blit(temp1, temp2, mat, 0); mat.SetVector("_offsets", new Vector4(samplerScale, 0, 0, 0)); Graphics.Blit(temp2, temp1, mat, 0); //景深操作,景深需要兩的模糊效果圖我們通過_BlurTex變量傳入shader mat.SetTexture("_BlurTex", temp1); //設置shader的參數,主要是焦點和遠近模糊的權重,權重可以控制插值時使用模糊圖片的權重 mat.SetFloat("_focalDistance", FocalDistance01(focalDistance)); mat.SetFloat("_nearBlurScale", nearBlurScale); mat.SetFloat("_farBlurScale", farBlurScale); //使用pass1進行景深效果計算,清晰場景圖直接從source輸入到shader的_MainTex中 Graphics.Blit(src, dest, mat, 1); //釋放申請的RT RenderTexture.ReleaseTemporary(temp1); RenderTexture.ReleaseTemporary(temp2); } } //計算設置的焦點被轉換到01空間中的距離,以便shader中通過這個01空間的焦點距離與depth比較 private float FocalDistance01(float distance) { float dist = Cam.WorldToViewportPoint((distance - Cam.nearClipPlane) * Cam.transform.forward + Cam.transform.position).z / (Cam.farClipPlane - Cam.nearClipPlane); return dist; } }