using UnityEngine; namespace UnityStandardAssets.ImageEffects { [ExecuteInEditMode] [RequireComponent(typeof(Camera))] [AddComponentMenu("Image Effects/Camera/Depth of Field (deprecated)")] public class DepthOfFieldDeprecated : PostEffectsBase { public enum Dof34QualitySetting { OnlyBackground = 1, BackgroundAndForeground = 2 } public enum DofResolution { High = 2, Medium = 3, Low = 4 } public enum DofBlurriness { Low = 1, High = 2, VeryHigh = 4 } public enum BokehDestination { Background = 1, Foreground = 2, BackgroundAndForeground = 3 } private static int SMOOTH_DOWNSAMPLE_PASS = 6; private static float BOKEH_EXTRA_BLUR = 2f; public Dof34QualitySetting quality = Dof34QualitySetting.OnlyBackground; public DofResolution resolution = DofResolution.Low; public bool simpleTweakMode = true; public float focalPoint = 1f; public float smoothness = 0.5f; public float focalZDistance; public float focalZStartCurve = 1f; public float focalZEndCurve = 1f; private float focalStartCurve = 2f; private float focalEndCurve = 2f; private float focalDistance01 = 0.1f; public Transform objectFocus; public float focalSize; public DofBlurriness bluriness = DofBlurriness.High; public float maxBlurSpread = 1.75f; public float foregroundBlurExtrude = 1.15f; public Shader dofBlurShader; private Material dofBlurMaterial; public Shader dofShader; private Material dofMaterial; public bool visualize; public BokehDestination bokehDestination = BokehDestination.Background; private float widthOverHeight = 1.25f; private float oneOverBaseSize = 0.001953125f; public bool bokeh; public bool bokehSupport = true; public Shader bokehShader; public Texture2D bokehTexture; public float bokehScale = 2.4f; public float bokehIntensity = 0.15f; public float bokehThresholdContrast = 0.1f; public float bokehThresholdLuminance = 0.55f; public int bokehDownsample = 1; private Material bokehMaterial; private Camera _camera; private RenderTexture foregroundTexture; private RenderTexture mediumRezWorkTexture; private RenderTexture finalDefocus; private RenderTexture lowRezWorkTexture; private RenderTexture bokehSource; private RenderTexture bokehSource2; private void CreateMaterials() { dofBlurMaterial = CheckShaderAndCreateMaterial(dofBlurShader, dofBlurMaterial); dofMaterial = CheckShaderAndCreateMaterial(dofShader, dofMaterial); bokehSupport = bokehShader.isSupported; if (bokeh && bokehSupport && (bool)bokehShader) { bokehMaterial = CheckShaderAndCreateMaterial(bokehShader, bokehMaterial); } } public override bool CheckResources() { CheckSupport(true); dofBlurMaterial = CheckShaderAndCreateMaterial(dofBlurShader, dofBlurMaterial); dofMaterial = CheckShaderAndCreateMaterial(dofShader, dofMaterial); bokehSupport = bokehShader.isSupported; if (bokeh && bokehSupport && (bool)bokehShader) { bokehMaterial = CheckShaderAndCreateMaterial(bokehShader, bokehMaterial); } if (!isSupported) { ReportAutoDisable(); } return isSupported; } private void OnDisable() { Quads.Cleanup(); } private void OnEnable() { _camera = GetComponent(); _camera.depthTextureMode |= DepthTextureMode.Depth; } private float FocalDistance01(float worldDist) { return _camera.WorldToViewportPoint((worldDist - _camera.nearClipPlane) * _camera.transform.forward + _camera.transform.position).z / (_camera.farClipPlane - _camera.nearClipPlane); } private int GetDividerBasedOnQuality() { int result = 1; if (resolution == DofResolution.Medium) { result = 2; } else if (resolution == DofResolution.Low) { result = 2; } return result; } private int GetLowResolutionDividerBasedOnQuality(int baseDivider) { int num = baseDivider; if (resolution == DofResolution.High) { num *= 2; } if (resolution == DofResolution.Low) { num *= 2; } return num; } private void OnRenderImage(RenderTexture source, RenderTexture destination) { if (!CheckResources()) { Graphics.Blit(source, destination); return; } if (smoothness < 0.1f) { smoothness = 0.1f; } bokeh = bokeh && bokehSupport; float num = ((!bokeh) ? 1f : BOKEH_EXTRA_BLUR); bool flag = quality > Dof34QualitySetting.OnlyBackground; float num2 = focalSize / (_camera.farClipPlane - _camera.nearClipPlane); if (simpleTweakMode) { focalDistance01 = ((!objectFocus) ? FocalDistance01(focalPoint) : (_camera.WorldToViewportPoint(objectFocus.position).z / _camera.farClipPlane)); focalStartCurve = focalDistance01 * smoothness; focalEndCurve = focalStartCurve; flag = flag && focalPoint > _camera.nearClipPlane + Mathf.Epsilon; } else { if ((bool)objectFocus) { Vector3 vector = _camera.WorldToViewportPoint(objectFocus.position); vector.z /= _camera.farClipPlane; focalDistance01 = vector.z; } else { focalDistance01 = FocalDistance01(focalZDistance); } focalStartCurve = focalZStartCurve; focalEndCurve = focalZEndCurve; flag = flag && focalPoint > _camera.nearClipPlane + Mathf.Epsilon; } widthOverHeight = 1f * (float)source.width / (1f * (float)source.height); oneOverBaseSize = 0.001953125f; dofMaterial.SetFloat("_ForegroundBlurExtrude", foregroundBlurExtrude); dofMaterial.SetVector("_CurveParams", new Vector4((!simpleTweakMode) ? focalStartCurve : (1f / focalStartCurve), (!simpleTweakMode) ? focalEndCurve : (1f / focalEndCurve), num2 * 0.5f, focalDistance01)); dofMaterial.SetVector("_InvRenderTargetSize", new Vector4(1f / (1f * (float)source.width), 1f / (1f * (float)source.height), 0f, 0f)); int dividerBasedOnQuality = GetDividerBasedOnQuality(); int lowResolutionDividerBasedOnQuality = GetLowResolutionDividerBasedOnQuality(dividerBasedOnQuality); AllocateTextures(flag, source, dividerBasedOnQuality, lowResolutionDividerBasedOnQuality); Graphics.Blit(source, source, dofMaterial, 3); Downsample(source, mediumRezWorkTexture); Blur(mediumRezWorkTexture, mediumRezWorkTexture, DofBlurriness.Low, 4, maxBlurSpread); if (bokeh && (BokehDestination.Foreground & bokehDestination) != 0) { dofMaterial.SetVector("_Threshhold", new Vector4(bokehThresholdContrast, bokehThresholdLuminance, 0.95f, 0f)); Graphics.Blit(mediumRezWorkTexture, bokehSource2, dofMaterial, 11); Graphics.Blit(mediumRezWorkTexture, lowRezWorkTexture); Blur(lowRezWorkTexture, lowRezWorkTexture, bluriness, 0, maxBlurSpread * num); } else { Downsample(mediumRezWorkTexture, lowRezWorkTexture); Blur(lowRezWorkTexture, lowRezWorkTexture, bluriness, 0, maxBlurSpread); } dofBlurMaterial.SetTexture("_TapLow", lowRezWorkTexture); dofBlurMaterial.SetTexture("_TapMedium", mediumRezWorkTexture); Graphics.Blit(null, finalDefocus, dofBlurMaterial, 3); if (bokeh && (BokehDestination.Foreground & bokehDestination) != 0) { AddBokeh(bokehSource2, bokehSource, finalDefocus); } dofMaterial.SetTexture("_TapLowBackground", finalDefocus); dofMaterial.SetTexture("_TapMedium", mediumRezWorkTexture); Graphics.Blit(source, (!flag) ? destination : foregroundTexture, dofMaterial, visualize ? 2 : 0); if (flag) { Graphics.Blit(foregroundTexture, source, dofMaterial, 5); Downsample(source, mediumRezWorkTexture); BlurFg(mediumRezWorkTexture, mediumRezWorkTexture, DofBlurriness.Low, 2, maxBlurSpread); if (bokeh && (BokehDestination.Foreground & bokehDestination) != 0) { dofMaterial.SetVector("_Threshhold", new Vector4(bokehThresholdContrast * 0.5f, bokehThresholdLuminance, 0f, 0f)); Graphics.Blit(mediumRezWorkTexture, bokehSource2, dofMaterial, 11); Graphics.Blit(mediumRezWorkTexture, lowRezWorkTexture); BlurFg(lowRezWorkTexture, lowRezWorkTexture, bluriness, 1, maxBlurSpread * num); } else { BlurFg(mediumRezWorkTexture, lowRezWorkTexture, bluriness, 1, maxBlurSpread); } Graphics.Blit(lowRezWorkTexture, finalDefocus); dofMaterial.SetTexture("_TapLowForeground", finalDefocus); Graphics.Blit(source, destination, dofMaterial, visualize ? 1 : 4); if (bokeh && (BokehDestination.Foreground & bokehDestination) != 0) { AddBokeh(bokehSource2, bokehSource, destination); } } ReleaseTextures(); } private void Blur(RenderTexture from, RenderTexture to, DofBlurriness iterations, int blurPass, float spread) { RenderTexture temporary = RenderTexture.GetTemporary(to.width, to.height); if (iterations > DofBlurriness.Low) { BlurHex(from, to, blurPass, spread, temporary); if (iterations > DofBlurriness.High) { dofBlurMaterial.SetVector("offsets", new Vector4(0f, spread * oneOverBaseSize, 0f, 0f)); Graphics.Blit(to, temporary, dofBlurMaterial, blurPass); dofBlurMaterial.SetVector("offsets", new Vector4(spread / widthOverHeight * oneOverBaseSize, 0f, 0f, 0f)); Graphics.Blit(temporary, to, dofBlurMaterial, blurPass); } } else { dofBlurMaterial.SetVector("offsets", new Vector4(0f, spread * oneOverBaseSize, 0f, 0f)); Graphics.Blit(from, temporary, dofBlurMaterial, blurPass); dofBlurMaterial.SetVector("offsets", new Vector4(spread / widthOverHeight * oneOverBaseSize, 0f, 0f, 0f)); Graphics.Blit(temporary, to, dofBlurMaterial, blurPass); } RenderTexture.ReleaseTemporary(temporary); } private void BlurFg(RenderTexture from, RenderTexture to, DofBlurriness iterations, int blurPass, float spread) { dofBlurMaterial.SetTexture("_TapHigh", from); RenderTexture temporary = RenderTexture.GetTemporary(to.width, to.height); if (iterations > DofBlurriness.Low) { BlurHex(from, to, blurPass, spread, temporary); if (iterations > DofBlurriness.High) { dofBlurMaterial.SetVector("offsets", new Vector4(0f, spread * oneOverBaseSize, 0f, 0f)); Graphics.Blit(to, temporary, dofBlurMaterial, blurPass); dofBlurMaterial.SetVector("offsets", new Vector4(spread / widthOverHeight * oneOverBaseSize, 0f, 0f, 0f)); Graphics.Blit(temporary, to, dofBlurMaterial, blurPass); } } else { dofBlurMaterial.SetVector("offsets", new Vector4(0f, spread * oneOverBaseSize, 0f, 0f)); Graphics.Blit(from, temporary, dofBlurMaterial, blurPass); dofBlurMaterial.SetVector("offsets", new Vector4(spread / widthOverHeight * oneOverBaseSize, 0f, 0f, 0f)); Graphics.Blit(temporary, to, dofBlurMaterial, blurPass); } RenderTexture.ReleaseTemporary(temporary); } private void BlurHex(RenderTexture from, RenderTexture to, int blurPass, float spread, RenderTexture tmp) { dofBlurMaterial.SetVector("offsets", new Vector4(0f, spread * oneOverBaseSize, 0f, 0f)); Graphics.Blit(from, tmp, dofBlurMaterial, blurPass); dofBlurMaterial.SetVector("offsets", new Vector4(spread / widthOverHeight * oneOverBaseSize, 0f, 0f, 0f)); Graphics.Blit(tmp, to, dofBlurMaterial, blurPass); dofBlurMaterial.SetVector("offsets", new Vector4(spread / widthOverHeight * oneOverBaseSize, spread * oneOverBaseSize, 0f, 0f)); Graphics.Blit(to, tmp, dofBlurMaterial, blurPass); dofBlurMaterial.SetVector("offsets", new Vector4(spread / widthOverHeight * oneOverBaseSize, (0f - spread) * oneOverBaseSize, 0f, 0f)); Graphics.Blit(tmp, to, dofBlurMaterial, blurPass); } private void Downsample(RenderTexture from, RenderTexture to) { dofMaterial.SetVector("_InvRenderTargetSize", new Vector4(1f / (1f * (float)to.width), 1f / (1f * (float)to.height), 0f, 0f)); Graphics.Blit(from, to, dofMaterial, SMOOTH_DOWNSAMPLE_PASS); } private void AddBokeh(RenderTexture bokehInfo, RenderTexture tempTex, RenderTexture finalTarget) { if (!bokehMaterial) { return; } Mesh[] meshes = Quads.GetMeshes(tempTex.width, tempTex.height); RenderTexture.active = tempTex; GL.Clear(false, true, new Color(0f, 0f, 0f, 0f)); GL.PushMatrix(); GL.LoadIdentity(); bokehInfo.filterMode = FilterMode.Point; float num = (float)bokehInfo.width * 1f / ((float)bokehInfo.height * 1f); float num2 = 2f / (1f * (float)bokehInfo.width); num2 += bokehScale * maxBlurSpread * BOKEH_EXTRA_BLUR * oneOverBaseSize; bokehMaterial.SetTexture("_Source", bokehInfo); bokehMaterial.SetTexture("_MainTex", bokehTexture); bokehMaterial.SetVector("_ArScale", new Vector4(num2, num2 * num, 0.5f, 0.5f * num)); bokehMaterial.SetFloat("_Intensity", bokehIntensity); bokehMaterial.SetPass(0); Mesh[] array = meshes; foreach (Mesh mesh in array) { if ((bool)mesh) { Graphics.DrawMeshNow(mesh, Matrix4x4.identity); } } GL.PopMatrix(); Graphics.Blit(tempTex, finalTarget, dofMaterial, 8); bokehInfo.filterMode = FilterMode.Bilinear; } private void ReleaseTextures() { if ((bool)foregroundTexture) { RenderTexture.ReleaseTemporary(foregroundTexture); } if ((bool)finalDefocus) { RenderTexture.ReleaseTemporary(finalDefocus); } if ((bool)mediumRezWorkTexture) { RenderTexture.ReleaseTemporary(mediumRezWorkTexture); } if ((bool)lowRezWorkTexture) { RenderTexture.ReleaseTemporary(lowRezWorkTexture); } if ((bool)bokehSource) { RenderTexture.ReleaseTemporary(bokehSource); } if ((bool)bokehSource2) { RenderTexture.ReleaseTemporary(bokehSource2); } } private void AllocateTextures(bool blurForeground, RenderTexture source, int divider, int lowTexDivider) { foregroundTexture = null; if (blurForeground) { foregroundTexture = RenderTexture.GetTemporary(source.width, source.height, 0); } mediumRezWorkTexture = RenderTexture.GetTemporary(source.width / divider, source.height / divider, 0); finalDefocus = RenderTexture.GetTemporary(source.width / divider, source.height / divider, 0); lowRezWorkTexture = RenderTexture.GetTemporary(source.width / lowTexDivider, source.height / lowTexDivider, 0); bokehSource = null; bokehSource2 = null; if (bokeh) { bokehSource = RenderTexture.GetTemporary(source.width / (lowTexDivider * bokehDownsample), source.height / (lowTexDivider * bokehDownsample), 0, RenderTextureFormat.ARGBHalf); bokehSource2 = RenderTexture.GetTemporary(source.width / (lowTexDivider * bokehDownsample), source.height / (lowTexDivider * bokehDownsample), 0, RenderTextureFormat.ARGBHalf); bokehSource.filterMode = FilterMode.Bilinear; bokehSource2.filterMode = FilterMode.Bilinear; RenderTexture.active = bokehSource2; GL.Clear(false, true, new Color(0f, 0f, 0f, 0f)); } source.filterMode = FilterMode.Bilinear; finalDefocus.filterMode = FilterMode.Bilinear; mediumRezWorkTexture.filterMode = FilterMode.Bilinear; lowRezWorkTexture.filterMode = FilterMode.Bilinear; if ((bool)foregroundTexture) { foregroundTexture.filterMode = FilterMode.Bilinear; } } } }