using System.Collections; using System.Collections.Generic; using UnityEngine; // Unit的一种后处理效果,渲染到一个RT上,对这个RT做效果 public class UnitImageEffectHolder { public float size; public GameObject gameObject; public MeshRenderer renderer { get { if (gameObject == null) return null; return gameObject.GetComponent(); } } } public class UnitImageEffectHandle { public delegate void UnitImageEffectStepCallback(float normalizedTime); public delegate void UnitImageEffectEndCallback(); public float lifeTime; public float curTime; public UnitImageEffectHolder holder; public UnitImageEffectStepCallback stepFunc; public UnitImageEffectEndCallback onStop; } public class UnitImageEffect : UnitComponent { public List effects = new List(); public static GameObject effectPlane; private Dictionary/*pool*/> m_HolderPool = new Dictionary>(); private ObjectPool m_HandlePool = new ObjectPool(null, null); public override void OnUpdate() { base.OnUpdate(); List temp = ListPool.Get(); for(int i = 0; i < effects.Count; ++i) { var handle = effects[i]; handle.curTime += Time.deltaTime; if(handle.curTime > handle.lifeTime) { temp.Add(handle); handle.onStop?.Invoke(); continue; } handle.stepFunc?.Invoke(handle.curTime / handle.lifeTime); } for(int j = 0; j < temp.Count; j++) { temp[j].holder.gameObject.SetActive(false); ReleaseHolder(ref temp[j].holder); effects.Remove(temp[j]); m_HandlePool.Release(temp[j]); } ListPool.Release(temp); } UnitImageEffectHolder ClaimHolder(float size) { List holders; if (m_HolderPool.TryGetValue(size, out holders)) { if (holders.Count > 0) { var holder = holders[holders.Count - 1]; holders.RemoveAt(holders.Count - 1); return holder; } } UnitImageEffectHolder newHolder = new UnitImageEffectHolder(); newHolder.size = size; Mesh mesh = new Mesh(); mesh.vertices = new Vector3[4] { new Vector3(-size/2, size/2, 0), new Vector3(size/2, size/2, 0), new Vector3(size/2, -size/2, 0), new Vector3(-size/2, -size/2, 0) }; mesh.uv = new Vector2[4] { new Vector2(0, 1), new Vector2(1, 1), new Vector2(1, 0), new Vector2(0, 0), }; mesh.triangles = new int[6] { 0, 1, 3, 1, 2, 3, }; mesh.UploadMeshData(true); newHolder.gameObject = new GameObject("Image Effect Holder(" + size + "m)"); MeshFilter filter = newHolder.gameObject.AddComponent(); filter.sharedMesh = mesh; MeshRenderer renderer = newHolder.gameObject.AddComponent(); renderer.lightProbeUsage = UnityEngine.Rendering.LightProbeUsage.Off; renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; renderer.receiveShadows = false; renderer.reflectionProbeUsage = UnityEngine.Rendering.ReflectionProbeUsage.Off; renderer.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion; renderer.allowOcclusionWhenDynamic = false; return newHolder; } void ReleaseHolder(ref UnitImageEffectHolder holder) { float size = holder.size; List holders; if (!m_HolderPool.TryGetValue(size, out holders)) { holders = new List(); m_HolderPool.Add(size, holders); } holder.gameObject.SetActive(false); holder.gameObject.transform.position = Vector3.zero; holders.Add(holder); holder = null; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public void ShowMotionBlur(float lifeTime, float angle, float distance) { UnitImageEffectHandle handle = m_HandlePool.Get(); handle.lifeTime = lifeTime; handle.curTime = 0; float size = UnitManager.Instance.pc.unitDetail.snapshotBound; handle.holder = ClaimHolder(size); handle.holder.gameObject.SetActive(true); string matPath = StaticDefine.imageEffectMaterails[EImageEffectMaterails.MotionBlur]; handle.holder.renderer.sharedMaterial = ResourceManager.Instance.LoadAsset(matPath); MaterialPropertyBlock block = new MaterialPropertyBlock(); handle.holder.renderer.GetPropertyBlock(block); block.SetFloat("_Angle", angle); block.SetFloat("_Distance", distance); handle.holder.renderer.SetPropertyBlock(block); handle.stepFunc = (float normalTime) => { handle.holder.gameObject.transform.position = UnitManager.Instance.pc.center; handle.holder.renderer.GetPropertyBlock(block); block.SetFloat("_Distance", /*(normalTime) * */distance); handle.holder.renderer.SetPropertyBlock(block); }; effects.Add(handle); } public void ShowGlitch(float lifeTime, bool hideUnitInMainCamera = true) { PCController pc = UnitManager.Instance.pc as PCController; UnitImageEffectHandle handle = m_HandlePool.Get(); handle.lifeTime = lifeTime; handle.curTime = 0; float size = UnitManager.Instance.pc.unitDetail.snapshotBound; handle.holder = ClaimHolder(size); handle.holder.gameObject.SetActive(true); string matPath = StaticDefine.imageEffectMaterails[EImageEffectMaterails.Glitch]; handle.holder.renderer.sharedMaterial = ResourceManager.Instance.LoadAsset(matPath); MaterialPropertyBlock block = new MaterialPropertyBlock(); handle.holder.renderer.GetPropertyBlock(block); handle.holder.renderer.SetPropertyBlock(block); handle.stepFunc = (float normalTime) => { UnitCamera.Instance.Render(); handle.holder.gameObject.transform.position = UnitManager.Instance.pc.center; handle.holder.renderer.GetPropertyBlock(block); handle.holder.renderer.SetPropertyBlock(block); }; if (hideUnitInMainCamera) { pc.unitRender.SetVisibilityInAllCameras(false); } handle.onStop = () => { pc.unitRender.SetVisibilityInAllCameras(true); }; effects.Add(handle); } }