using UnityEngine.Rendering; 
 | 
  
 | 
namespace UnityEngine.PostProcessing 
 | 
{ 
 | 
    using DebugMode = BuiltinDebugViewsModel.Mode; 
 | 
  
 | 
    public sealed class DepthOfFieldComponent : PostProcessingComponentRenderTexture<DepthOfFieldModel> 
 | 
    { 
 | 
        static class Uniforms 
 | 
        { 
 | 
            internal static readonly int _DepthOfFieldTex    = Shader.PropertyToID("_DepthOfFieldTex"); 
 | 
            internal static readonly int _DepthOfFieldCoCTex = Shader.PropertyToID("_DepthOfFieldCoCTex"); 
 | 
            internal static readonly int _Distance           = Shader.PropertyToID("_Distance"); 
 | 
            internal static readonly int _LensCoeff          = Shader.PropertyToID("_LensCoeff"); 
 | 
            internal static readonly int _MaxCoC             = Shader.PropertyToID("_MaxCoC"); 
 | 
            internal static readonly int _RcpMaxCoC          = Shader.PropertyToID("_RcpMaxCoC"); 
 | 
            internal static readonly int _RcpAspect          = Shader.PropertyToID("_RcpAspect"); 
 | 
            internal static readonly int _MainTex            = Shader.PropertyToID("_MainTex"); 
 | 
            internal static readonly int _CoCTex             = Shader.PropertyToID("_CoCTex"); 
 | 
            internal static readonly int _TaaParams          = Shader.PropertyToID("_TaaParams"); 
 | 
            internal static readonly int _DepthOfFieldParams = Shader.PropertyToID("_DepthOfFieldParams"); 
 | 
        } 
 | 
  
 | 
        const string k_ShaderString = "Hidden/Post FX/Depth Of Field"; 
 | 
  
 | 
        public override bool active 
 | 
        { 
 | 
            get 
 | 
            { 
 | 
                return model.enabled 
 | 
                       && !context.interrupted; 
 | 
            } 
 | 
        } 
 | 
  
 | 
        public override DepthTextureMode GetCameraFlags() 
 | 
        { 
 | 
            return DepthTextureMode.Depth; 
 | 
        } 
 | 
  
 | 
        RenderTexture m_CoCHistory; 
 | 
  
 | 
        // Height of the 35mm full-frame format (36mm x 24mm) 
 | 
        const float k_FilmHeight = 0.024f; 
 | 
  
 | 
        float CalculateFocalLength() 
 | 
        { 
 | 
            var settings = model.settings; 
 | 
  
 | 
            if (!settings.useCameraFov) 
 | 
                return settings.focalLength / 1000f; 
 | 
  
 | 
            float fov = context.camera.fieldOfView * Mathf.Deg2Rad; 
 | 
            return 0.5f * k_FilmHeight / Mathf.Tan(0.5f * fov); 
 | 
        } 
 | 
  
 | 
        float CalculateMaxCoCRadius(int screenHeight) 
 | 
        { 
 | 
            // Estimate the allowable maximum radius of CoC from the kernel 
 | 
            // size (the equation below was empirically derived). 
 | 
            float radiusInPixels = (float)model.settings.kernelSize * 4f + 6f; 
 | 
  
 | 
            // Applying a 5% limit to the CoC radius to keep the size of 
 | 
            // TileMax/NeighborMax small enough. 
 | 
            return Mathf.Min(0.05f, radiusInPixels / screenHeight); 
 | 
        } 
 | 
  
 | 
        bool CheckHistory(int width, int height) 
 | 
        { 
 | 
            return m_CoCHistory != null && m_CoCHistory.IsCreated() && 
 | 
                m_CoCHistory.width == width && m_CoCHistory.height == height; 
 | 
        } 
 | 
  
 | 
        RenderTextureFormat SelectFormat(RenderTextureFormat primary, RenderTextureFormat secondary) 
 | 
        { 
 | 
            if (SystemInfo.SupportsRenderTextureFormat(primary)) return primary; 
 | 
            if (SystemInfo.SupportsRenderTextureFormat(secondary)) return secondary; 
 | 
            return RenderTextureFormat.Default; 
 | 
        } 
 | 
  
 | 
        public void Prepare(RenderTexture source, Material uberMaterial, bool antialiasCoC, Vector2 taaJitter, float taaBlending) 
 | 
        { 
 | 
            var settings = model.settings; 
 | 
            var colorFormat = RenderTextureFormat.DefaultHDR; 
 | 
            var cocFormat = SelectFormat(RenderTextureFormat.R8, RenderTextureFormat.RHalf); 
 | 
  
 | 
            // Avoid using R8 on OSX with Metal. #896121, https://goo.gl/MgKqu6 
 | 
            #if (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX) && !UNITY_2017_1_OR_NEWER 
 | 
            if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Metal) 
 | 
                cocFormat = SelectFormat(RenderTextureFormat.RHalf, RenderTextureFormat.Default); 
 | 
            #endif 
 | 
  
 | 
            // Material setup 
 | 
            var f = CalculateFocalLength(); 
 | 
            var s1 = Mathf.Max(settings.focusDistance, f); 
 | 
            var aspect = (float)source.width / source.height; 
 | 
            var coeff = f * f / (settings.aperture * (s1 - f) * k_FilmHeight * 2); 
 | 
            var maxCoC = CalculateMaxCoCRadius(source.height); 
 | 
  
 | 
            var material = context.materialFactory.Get(k_ShaderString); 
 | 
            material.SetFloat(Uniforms._Distance, s1); 
 | 
            material.SetFloat(Uniforms._LensCoeff, coeff); 
 | 
            material.SetFloat(Uniforms._MaxCoC, maxCoC); 
 | 
            material.SetFloat(Uniforms._RcpMaxCoC, 1f / maxCoC); 
 | 
            material.SetFloat(Uniforms._RcpAspect, 1f / aspect); 
 | 
  
 | 
            // CoC calculation pass 
 | 
            var rtCoC = context.renderTextureFactory.Get(context.width, context.height, 0, cocFormat, RenderTextureReadWrite.Linear); 
 | 
            Graphics.Blit(null, rtCoC, material, 0); 
 | 
  
 | 
            if (antialiasCoC) 
 | 
            { 
 | 
                // CoC temporal filter pass 
 | 
                material.SetTexture(Uniforms._CoCTex, rtCoC); 
 | 
  
 | 
                var blend = CheckHistory(context.width, context.height) ? taaBlending : 0f; 
 | 
                material.SetVector(Uniforms._TaaParams, new Vector3(taaJitter.x, taaJitter.y, blend)); 
 | 
  
 | 
                var rtFiltered = RenderTexture.GetTemporary(context.width, context.height, 0, cocFormat); 
 | 
                Graphics.Blit(m_CoCHistory, rtFiltered, material, 1); 
 | 
  
 | 
                context.renderTextureFactory.Release(rtCoC); 
 | 
                if (m_CoCHistory != null) RenderTexture.ReleaseTemporary(m_CoCHistory); 
 | 
  
 | 
                m_CoCHistory = rtCoC = rtFiltered; 
 | 
            } 
 | 
  
 | 
            // Downsampling and prefiltering pass 
 | 
            var rt1 = context.renderTextureFactory.Get(context.width / 2, context.height / 2, 0, colorFormat); 
 | 
            material.SetTexture(Uniforms._CoCTex, rtCoC); 
 | 
            Graphics.Blit(source, rt1, material, 2); 
 | 
  
 | 
            // Bokeh simulation pass 
 | 
            var rt2 = context.renderTextureFactory.Get(context.width / 2, context.height / 2, 0, colorFormat); 
 | 
            Graphics.Blit(rt1, rt2, material, 3 + (int)settings.kernelSize); 
 | 
  
 | 
            // Postfilter pass 
 | 
            Graphics.Blit(rt2, rt1, material, 7); 
 | 
  
 | 
            // Give the results to the uber shader. 
 | 
            uberMaterial.SetVector(Uniforms._DepthOfFieldParams, new Vector3(s1, coeff, maxCoC)); 
 | 
  
 | 
            if (context.profile.debugViews.IsModeActive(DebugMode.FocusPlane)) 
 | 
            { 
 | 
                uberMaterial.EnableKeyword("DEPTH_OF_FIELD_COC_VIEW"); 
 | 
                context.Interrupt(); 
 | 
            } 
 | 
            else 
 | 
            { 
 | 
                uberMaterial.SetTexture(Uniforms._DepthOfFieldTex, rt1); 
 | 
                uberMaterial.SetTexture(Uniforms._DepthOfFieldCoCTex, rtCoC); 
 | 
                uberMaterial.EnableKeyword("DEPTH_OF_FIELD"); 
 | 
            } 
 | 
  
 | 
            context.renderTextureFactory.Release(rt2); 
 | 
        } 
 | 
  
 | 
        public override void OnDisable() 
 | 
        { 
 | 
            if (m_CoCHistory != null) 
 | 
                RenderTexture.ReleaseTemporary(m_CoCHistory); 
 | 
  
 | 
            m_CoCHistory = null; 
 | 
        } 
 | 
    } 
 | 
} 
 |