From 6eb915c129fc90c6f4c82ae097dd6ffad5239efc Mon Sep 17 00:00:00 2001 From: chai Date: Mon, 25 Jan 2021 14:28:30 +0800 Subject: +scripts --- Client/Assets/Scripts/PostEffect/DOFHelper.cs | 383 ++++++++++++++++++++++++++ 1 file changed, 383 insertions(+) create mode 100644 Client/Assets/Scripts/PostEffect/DOFHelper.cs (limited to 'Client/Assets/Scripts/PostEffect/DOFHelper.cs') diff --git a/Client/Assets/Scripts/PostEffect/DOFHelper.cs b/Client/Assets/Scripts/PostEffect/DOFHelper.cs new file mode 100644 index 00000000..26188d28 --- /dev/null +++ b/Client/Assets/Scripts/PostEffect/DOFHelper.cs @@ -0,0 +1,383 @@ +//Unity Scatter DOF (disk blur): 13ms +//Unity Scatter DOF (DX11): 6ms +//FxPro DOF with bokeh: 5.2ms +//FxPro DOF no bokeh: 3.9ms + +#define FXPRO_EFFECT +//#define DOFPRO_EFFECT + +#if FXPRO_EFFECT +#define BLOOMPRO_EFFECT +#define DOFPRO_EFFECT +#endif + +using System; +using UnityEngine; +using System.Collections.Generic; + +using Object = UnityEngine.Object; + +#if FXPRO_EFFECT +namespace FxProNS { +#elif DOFPRO_EFFECT +namespace DOFProNS { +#endif + [Serializable] + public class DOFHelperParams { + //Parameters coming from DOFPro + public bool UseUnityDepthBuffer = false; + public bool AutoFocus = true; + + public LayerMask AutoFocusLayerMask = -1; + + [Range( 2f, 8f )] + public float AutoFocusSpeed = 5f; + + [Range( .01f, 1f )] + public float FocalLengthMultiplier = .33f; + + public float FocalDistMultiplier = 1f; + + [Range( .5f, 2f )] + public float DOFBlurSize = 1f; + + public bool BokehEnabled = false; + + [Range( 2f, 8f )] + public float DepthCompression = 4f; + public Camera EffectCamera; + public Transform Target; + + [Range( 0f, 1f )] + public float BokehThreshold = .5f; + + [Range( .5f, 5f )] + public float BokehGain = 2f; + + [Range( 0f, 1f )] + public float BokehBias = .5f; + + public bool DoubleIntensityBlur = false; + } + + public class DOFHelper : Singleton, IDisposable + { + private static Material _mat; + + public static Material Mat + { + get + { + if (null == _mat) + { + Shader shader = XUtliPoolLib.ShaderManager.singleton.FindShader("DOFPro", "Hidden/DOFPro"); + _mat = new Material(shader) + { + hideFlags = HideFlags.HideAndDontSave + }; + } + + return _mat; + } + } + + private DOFHelperParams _p; + + public void SetParams(DOFHelperParams p) + { + _p = p; + } + + public void Init(bool searchForNonDepthmapAlphaObjects) + { + if (null == _p) + { + Debug.LogError("Call SetParams first"); + return; + } + + if (null == _p.EffectCamera) { + Debug.LogError("null == p.camera"); + return; + } + + if (null == Mat) + return; + + if (!_p.UseUnityDepthBuffer) + { + #if UNITY_EDITOR + if (searchForNonDepthmapAlphaObjects && GetNonDepthmapAlphaObjects().Length > 0) + { + Debug.LogError("Found non-alpha depthmapped shaders. Will be using Unity Depth Buffer instead. Warning: may be slow on mobile devices." + + + " Either make all shaders output depth value to alpha channel, or enable \"Use Unity Depth Buffer\" option."); + Debug.Break(); + _p.UseUnityDepthBuffer = true; + + if ( _p.EffectCamera.depthTextureMode != DepthTextureMode.DepthNormals) + _p.EffectCamera.depthTextureMode = DepthTextureMode.Depth; + + Mat.EnableKeyword("USE_CAMERA_DEPTH_TEXTURE"); + Mat.DisableKeyword("DONT_USE_CAMERA_DEPTH_TEXTURE"); + } + else + { + _p.EffectCamera.depthTextureMode = DepthTextureMode.None; + Mat.DisableKeyword("USE_CAMERA_DEPTH_TEXTURE"); + Mat.EnableKeyword("DONT_USE_CAMERA_DEPTH_TEXTURE"); + } + #else + _p.EffectCamera.depthTextureMode = DepthTextureMode.None; + Mat.DisableKeyword("USE_CAMERA_DEPTH_TEXTURE"); + Mat.EnableKeyword("DONT_USE_CAMERA_DEPTH_TEXTURE"); + #endif + } else { + if ( _p.EffectCamera.depthTextureMode != DepthTextureMode.DepthNormals ) + _p.EffectCamera.depthTextureMode = DepthTextureMode.Depth; + + Mat.EnableKeyword("USE_CAMERA_DEPTH_TEXTURE"); + Mat.DisableKeyword("DONT_USE_CAMERA_DEPTH_TEXTURE"); + } + + // Debug.Log( "p.useUnityDepthBuffer: " + p.useUnityDepthBuffer + "; p.camera.depthTextureMode: " + p.camera.depthTextureMode ); + + // UpdateQualitySettings(); + + // dofBoost = Mathf.Clamp(dofBoost, 1f, 10f); + _p.FocalLengthMultiplier = Mathf.Clamp(_p.FocalLengthMultiplier, .01f, .99f); + _p.DepthCompression = Mathf.Clamp(_p.DepthCompression, 1f, 10f); + + Shader.SetGlobalFloat("_OneOverDepthScale", _p.DepthCompression); + Shader.SetGlobalFloat("_OneOverDepthFar", 1f / (_p.EffectCamera.farClipPlane)); + + // mat.SetFloat("_DOFBoost", dofBoost); + + if ( _p.BokehEnabled ) + { + Mat.SetFloat( "_BokehThreshold", _p.BokehThreshold ); + Mat.SetFloat( "_BokehGain", _p.BokehGain ); + Mat.SetFloat( "_BokehBias", _p.BokehBias ); + } + } + + public void SetBlurRadius(int radius) + { + Shader.DisableKeyword("BLUR_RADIUS_10"); + Shader.DisableKeyword("BLUR_RADIUS_5"); + Shader.DisableKeyword("BLUR_RADIUS_3"); + Shader.DisableKeyword("BLUR_RADIUS_2"); + Shader.DisableKeyword("BLUR_RADIUS_1"); + + if (radius != 10 && radius != 5 && radius != 3 && radius != 2 && radius != 1) radius = 5; + + if ( radius < 3 ) radius = 3; + + //Debug.Log( "blur radius: " + radius ); + + Shader.EnableKeyword( "BLUR_RADIUS_" + radius ); + } + + private float _curAutoFocusDist = 0f; + + private void CalculateAndUpdateFocalDist() { + if (null == _p.EffectCamera) { + Debug.LogError("null == p.camera"); + return; + } + + float focalDist; + + if (!_p.AutoFocus && null != _p.Target) + { + Vector3 targetPosInViewportSpace = _p.EffectCamera.WorldToViewportPoint(_p.Target.position); + focalDist = targetPosInViewportSpace.z; + // float focalDist = (target.position - transform.position).magnitude / camera.farClipPlane; + } else + { + focalDist = _curAutoFocusDist = Mathf.Lerp(_curAutoFocusDist, CalculateAutoFocusDist(), Time.deltaTime * _p.AutoFocusSpeed); + // Debug.Log("focalDist: " + focalDist); + } + + focalDist /= _p.EffectCamera.farClipPlane; + + focalDist *= _p.FocalDistMultiplier * _p.DepthCompression; + + Mat.SetFloat("_FocalDist", focalDist); + + //Make sure that focalLength < focalDist + Mat.SetFloat("_FocalLength", focalDist * _p.FocalLengthMultiplier); + } + + private float CalculateAutoFocusDist() + { + if (null == _p.EffectCamera) return 0f; + + RaycastHit hitInfo; + + //Return farClipPlane if nothing was hit + + return Physics.Raycast( _p.EffectCamera.transform.position, _p.EffectCamera.transform.forward, out hitInfo, Mathf.Infinity, _p.AutoFocusLayerMask.value ) ? hitInfo.distance : _p.EffectCamera.farClipPlane; + } + + public void RenderCOCTexture(RenderTexture src, RenderTexture dest, float blurScale) + { + CalculateAndUpdateFocalDist(); + + if (null == _p.EffectCamera) { + Debug.LogError( "null == p.camera" ); + return; + } + + //Verify depth texture mode before rendering + if (_p.EffectCamera.depthTextureMode == DepthTextureMode.None) + _p.EffectCamera.depthTextureMode = DepthTextureMode.Depth; + + if (_p.DOFBlurSize > .001f) { + RenderTexture tempRt1 = RenderTextureManager.Instance.RequestRenderTexture( src.width, src.height, src.depth, src.format ); + RenderTexture tempRt2 = RenderTextureManager.Instance.RequestRenderTexture( src.width, src.height, src.depth, src.format ); + + Graphics.Blit( src, tempRt1, Mat, 0 ); + + //Blur COC texture + Mat.SetVector( "_SeparableBlurOffsets", new Vector4( blurScale, 0f, 0f, 0f ) ); + Graphics.Blit( tempRt1, tempRt2, Mat, 2 ); + Mat.SetVector( "_SeparableBlurOffsets", new Vector4( 0f, blurScale, 0f, 0f ) ); + Graphics.Blit( tempRt2, dest, Mat, 2 ); + + RenderTextureManager.Instance.ReleaseRenderTexture( tempRt1 ); + RenderTextureManager.Instance.ReleaseRenderTexture( tempRt2 ); + } + else { + Graphics.Blit( src, dest, Mat, 0 ); + } + } + + public void RenderDOFBlur( RenderTexture src, RenderTexture dest, RenderTexture cocTexture ) + { + //Graphics.Blit( src, dest ); + + if (null == cocTexture) { + Debug.LogError( "null == cocTexture" ); + return; + } + + Mat.SetTexture( "_COCTex", cocTexture ); + + // //Apply separable DOF + if ( _p.BokehEnabled ) + { + Mat.SetFloat( "_BlurIntensity", _p.DOFBlurSize ); + + Graphics.Blit( src, dest, Mat, 4 ); + } else { + RenderTexture tempRt = RenderTextureManager.Instance.RequestRenderTexture( src.width, src.height, src.depth, src.format ); + + Mat.SetVector( "_SeparableBlurOffsets", new Vector4( _p.DOFBlurSize, 0f, 0f, 0f ) ); + Graphics.Blit( src, tempRt, Mat, 1 ); + Mat.SetVector( "_SeparableBlurOffsets", new Vector4( 0f, _p.DOFBlurSize, 0f, 0f ) ); + Graphics.Blit( tempRt, dest, Mat, 1 ); + + RenderTextureManager.Instance.ReleaseRenderTexture( tempRt ); + } + } + + public void RenderEffect( RenderTexture src, RenderTexture dest ) { + RenderEffect( src, dest, false ); + } + + public void RenderEffect( RenderTexture src, RenderTexture dest, bool visualizeCOC ) + { + RenderTexture cocRenderTexture = RenderTextureManager.Instance.RequestRenderTexture( src.width, src.height, src.depth, src.format ); + RenderCOCTexture( src, cocRenderTexture, 0f ); + + //COC visualization + if (visualizeCOC) + { + Graphics.Blit(cocRenderTexture, dest); + RenderTextureManager.Instance.ReleaseRenderTexture(cocRenderTexture); + RenderTextureManager.Instance.ReleaseAllRenderTextures(); + return; + } + + RenderDOFBlur(src, dest, cocRenderTexture); + RenderTextureManager.Instance.ReleaseRenderTexture( cocRenderTexture ); + //RenderTextureManager.Instance.ReleaseAllRenderTextures(); + } + + public static GameObject[] GetNonDepthmapAlphaObjects() + { + if (!Application.isPlaying) + return new GameObject[0]; + + Renderer[] allRenderers = Object.FindObjectsOfType(); + + var selectedGOs = new List(); + var nonDepthMappedMaterial = new List(); + + foreach (Renderer rend in allRenderers) + { + if (null == rend.sharedMaterials) + continue; + + //Skip particle systems + if (null != rend.GetComponent()) + continue; + + foreach (Material mat in rend.sharedMaterials) + { + if (null == mat.shader) + continue; + + bool shouldFlagShader = null == mat.GetTag("RenderType", false); + + //Skip transparent materials + if (!shouldFlagShader && (mat.GetTag("RenderType", false).ToLower() == "transparent" || mat.GetTag("Queue", false).ToLower() == "transparent")) + continue; + + if (null == mat.GetTag("OUTPUT_DEPTH_TO_ALPHA", false) || mat.GetTag("OUTPUT_DEPTH_TO_ALPHA", false).ToLower() != "true") + { + // if (shouldLog) Debug.Log("OUTPUT_DEPTH_TO_ALPHA:" + mat.GetTag("OUTPUT_DEPTH_TO_ALPHA", false) ); + shouldFlagShader = true; + } + + // Debug.Log ("shouldFlagShader: " + shouldFlagShader); + + if (shouldFlagShader) + { + //Skip duplicates + if (nonDepthMappedMaterial.Contains(mat)) + continue; + + nonDepthMappedMaterial.Add(mat); + + Debug.Log( "Non-depthmapped: " + GetFullPath(rend.gameObject) ); + selectedGOs.Add(rend.gameObject); + } + } + } + + return selectedGOs.ToArray(); + } + + public static string GetFullPath(GameObject obj) + { + string path = "/" + obj.name; + while (obj.transform.parent != null) + { + obj = obj.transform.parent.gameObject; + path = "/" + obj.name + path; + } + return "'" + path + "'"; + } + + public void Dispose() + { + if (null != Mat) + Object.DestroyImmediate(Mat); + if (_p != null && _p.EffectCamera != null) + _p.EffectCamera.depthTextureMode = DepthTextureMode.None; + RenderTextureManager.Instance.Dispose(); + } + } +} \ No newline at end of file -- cgit v1.1-26-g67d0