summaryrefslogtreecommitdiff
path: root/Assets/Scripts/Unit/LensEffect/LensEffects.cs
blob: 4083eb8894056db9ce4aad9d0b48528fc3839eb3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
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<string/*shaderName*/, List<MaterialEntry>> m_MaterailPool;

	public static LensEffect Create(Func<LensEffect> create)
	{
		return create();
	}

	static LensEffect()
	{
		m_MaterailPool = new Dictionary<string, List<MaterialEntry>>();
	}

	static MaterialEntry ClaimMaterial(string shader)
	{
		List<MaterialEntry> 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<MaterialEntry> mats;
		if (!m_MaterailPool.TryGetValue(entry.shader, out mats))
		{
			mats = new List<MaterialEntry>();
			m_MaterailPool.Add(entry.shader, mats);
		}
		mats.Add(entry);
	}

	#region LensEffects

	public static LensEffect MotionBlur()
	{
		LensEffect eff = LensEffect.Create(() =>
		{
			LensEffect e = new LensEffect();

			List<MaterialEntry> materials = ListPool<MaterialEntry>.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<MeshFilter>().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 
}