using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering; public class MaterialEntry { public Material material; public string shader; } public struct ScaleOffset { public Vector2 scale; public Vector2 offset; } public class LensEffect { #region callbacks public delegate void BeforeIterateHandler(CommandBuffer cb); public BeforeIterateHandler beforeIterate; public delegate void IterationHandler(CommandBuffer cb, BodyPartRenderer renderer); public IterationHandler iterate; public delegate void AfterIterateHandler(CommandBuffer cb); public AfterIterateHandler afterIterate; // 这一帧的这个特效结束 public delegate void FinishRenderHandler(); public FinishRenderHandler finishRender; #endregion private static Dictionary> m_MaterailPool; public static LensEffect Create(Func create) { return create(); } static LensEffect() { m_MaterailPool = new Dictionary>(); } static MaterialEntry ClaimMaterial(string shader) { List mats; if (m_MaterailPool.TryGetValue(shader, out mats) && mats.Count > 0) { MaterialEntry me = mats[mats.Count - 1]; mats.RemoveAt(mats.Count - 1); return me; } Material mat = new Material(Shader.Find(shader)); MaterialEntry entry = new MaterialEntry(); entry.material = mat; entry.shader = shader; return entry; } static void ReleaseMaterial(MaterialEntry entry) { List mats; if (!m_MaterailPool.TryGetValue(entry.shader, out mats)) { mats = new List(); m_MaterailPool.Add(entry.shader, mats); } mats.Add(entry); } #region LensEffects public static LensEffect MotionBlur() { LensEffect eff = LensEffect.Create(() => { LensEffect e = new LensEffect(); List materials = ListPool.Get(); int tempID = Shader.PropertyToID("_Temp1"); ScaleOffset scaleOffset = new ScaleOffset(); e.beforeIterate = (CommandBuffer cb) => { cb.GetTemporaryRT(tempID, -1, -1, 24, FilterMode.Bilinear); cb.SetRenderTarget(tempID); cb.ClearRenderTarget(true, true, new Color(0, 0, 0, 0)); }; e.iterate = (CommandBuffer cb, BodyPartRenderer renderer) => { Matrix4x4 obj2Wod = Matrix4x4.identity; int subMeshCount = 0; if (renderer.renderer is SkinnedMeshRenderer) { SkinnedMeshRenderer smr = renderer.renderer as SkinnedMeshRenderer; Vector3 pos = smr.rootBone.transform.position; Quaternion rot = smr.rootBone.transform.rotation; obj2Wod = MatrixUtility.RotateAndTranslate(pos, rot); subMeshCount = smr.sharedMesh.subMeshCount; } else if (renderer.renderer is MeshRenderer) { obj2Wod = renderer.renderer.transform.localToWorldMatrix; subMeshCount = renderer.renderer.GetComponent().sharedMesh.subMeshCount; } for (int i = 0; i < subMeshCount; ++i) { MaterialEntry mat = ClaimMaterial(StaticDefine.shaders[EShader.SolidColor].name); materials.Add(mat); mat.material.SetColor("_Color", Color.red); mat.material.SetMatrix("_ObjectToWorld", obj2Wod); cb.DrawRenderer(renderer.renderer, mat.material, i); } }; e.afterIterate = (CommandBuffer cb) => { MaterialEntry blur = ClaimMaterial(StaticDefine.shaders[EShader.Blur].name); materials.Add(blur); cb.Blit(tempID, BuiltinRenderTextureType.CameraTarget, blur.material); }; e.finishRender = () => { for (int i = materials.Count - 1; i >= 0; --i) { MaterialEntry mat = materials[i]; ReleaseMaterial(mat); materials.RemoveAt(i); } }; return e; }); return eff; } public static LensEffect Glitch() { return null; } public static LensEffect OutLine() { return null; } public static LensEffect RimLight() { return null; } public static LensEffect Decals() { return null; } #endregion }