Unity中实现⽹格轮廓效果,选中边框效果(附带⾼斯模糊实现模
式,处理了锯齿情况)
问题背景:
最近要实现选中实体的⾼亮效果,要那种类似于unity中Outline的效果,⽹格轮廓⾼亮效果。
效果图:
具体代码:
OutlineEffect.cs
实体⾼亮效果类:
轮廓边总控制类,该脚本需要挂载到场景相机上
1using UnityEngine;
2using System.Collections.Generic;
3using UnityEngine.Rendering;
4
5namespace Tx3d.Framework
6 {
7 [DisallowMultipleComponent]
8 [RequireComponent(typeof(Camera))]
9 [ExecuteInEditMode]
10public class OutlineEffect : MonoBehaviour
11 {
12public static OutlineEffect Instance { get; private t; }
13
14private readonly LinkedSet<Outline> outlines = new LinkedSet<Outline>();
15
16 [Range(1.0f, 6.0f)]
17public float lineThickness = 1.0f;
18 [Range(0, 10)]
19public float lineIntensity = 1.2f;
20 [Range(0, 1)]
21public float fillAmount = 0.108f;
22
23public Color lineColor0 = llow;
24public Color lineColor1 = ;
25public Color lineColor2 = Color.blue;
26public Color lineColor3 = an;
27
28public bool additiveRendering = fal;
29
30public bool backfaceCulling = true;
31
32 [Header("The ttings can affect performance!")]
33public bool cornerOutlines = fal;
34public bool addLinesBetweenColors = fal;
35
36 [Header("Advanced ttings")]
37public bool scaleWithScreenSize = true;
38 [Range(0.1f, .9f)]
39public float alphaCutoff = .5f;
40public bool flipY = fal;
41public Camera sourceCamera;
42public bool autoEnableOutlines = true;
43
44 [HideInInspector]
45public Camera outlineCamera;
46 Material outline1Material;
47 Material outline2Material;
48 Material outline3Material;
49 Material outline4Material;
50 Material outlineEraMaterial;
51 Shader outlineShader;
52 Shader outlineBufferShader;
53 [HideInInspector]
54public Material outlineShaderMaterial;
55 [HideInInspector]
56public RenderTexture renderTexture;
57 [HideInInspector]
60 CommandBuffer commandBuffer;
61
62 Material GetMaterialFromID(int ID)
63 {
64if (ID == 0)
65return outline1Material;
66el if (ID == 1)
67return outline2Material;
个人总结学生68el if (ID == 2)
69return outline3Material;
70el if (ID == 3)
71return outline4Material;
72el
73return outline1Material;
74 }
75 List<Material> materialBuffer = new List<Material>();
76 Material CreateMaterial(Color emissionColor)
77 {
78 Material m = new Material(outlineBufferShader);
79 m.SetColor("_Color", emissionColor);
80 m.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
81 m.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
82 m.SetInt("_ZWrite", 0);
83 m.DisableKeyword("_ALPHATEST_ON");
84 m.EnableKeyword("_ALPHABLEND_ON");
85 m.DisableKeyword("_ALPHAPREMULTIPLY_ON");
86 m.renderQueue = 3000;
87return m;
88 }
89
90private void Awake()
91 {
92if (Instance != null)
93 {
94 Destroy(this);
95throw new System.Exception("you can only have one outline camera in the scene");
96 }
97
98 Instance = this;
99 }
100
101void Start()
102 {
103 CreateMaterialsIfNeeded();
104 UpdateMaterialsPublicProperties();
105
106if (sourceCamera == null)
107 {
108 sourceCamera = GetComponent<Camera>();
109
110if (sourceCamera == null)
111 sourceCamera = Camera.main;
112 }
113
114if (outlineCamera == null)
115 {
116foreach (Camera c in GetComponentsInChildren<Camera>())
117 {
118if (c.name == "Outline Camera")
119 {
120 outlineCamera = c;飞信群发
121 c.enabled = fal;
122
123break;
124 }
125 }
126
127if (outlineCamera == null)
128 {
129 GameObject cameraGameObject = new GameObject("Outline Camera");
130 ansform.parent = ansform;
131 outlineCamera = cameraGameObject.AddComponent<Camera>();
132 abled = fal;
133 }
134 }
135
136 renderTexture = new RenderTexture(sourceCamera.pixelWidth, sourceCamera.pixelHeight, 16, RenderTextureFormat.Default);
137 extraRenderTexture = new RenderTexture(sourceCamera.pixelWidth, sourceCamera.pixelHeight, 16, RenderTextureFormat.Default); 138 UpdateOutlineCameraFromSource();
139
140 commandBuffer = new CommandBuffer();
141 outlineCamera.AddCommandBuffer(CameraEvent.BeforeImageEffects, commandBuffer);
142 }
143
144bool RenderTheNextFrame;
145public void OnPreRender()
146 {
147if (commandBuffer == null)
149
150// the first frame during which there are no outlines, we still need to render
151// to clear out any outlines that were being rendered on the previous frame
152if (outlines.Count == 0)
153 {
154if (!RenderTheNextFrame)
155return;
156
157 RenderTheNextFrame = fal;
158 }
159el
160 {
161 RenderTheNextFrame = true;
162 }
163
164 CreateMaterialsIfNeeded();
165
166if (renderTexture == null || renderTexture.width != sourceCamera.pixelWidth || renderTexture.height != sourceCamera.pixelHeight)
167 {
168 renderTexture = new RenderTexture(sourceCamera.pixelWidth, sourceCamera.pixelHeight, 16, RenderTextureFormat.Default);
169 extraRenderTexture = new RenderTexture(sourceCamera.pixelWidth, sourceCamera.p
ixelHeight, 16, RenderTextureFormat.Default); 170 outlineCamera.targetTexture = renderTexture;
171 }
172 UpdateMaterialsPublicProperties();
173 UpdateOutlineCameraFromSource();
174 outlineCamera.targetTexture = renderTexture;
175 commandBuffer.SetRenderTarget(renderTexture);
176
177 commandBuffer.Clear();
178
179foreach (Outline outline in outlines)
180 {
181 LayerMask l = sourceCamera.cullingMask;
182
183// if (outline != null && l == (l | (1 << outline.gameObject.layer)))
184if (outline != null)
185 {
186for (int v = 0; v < outline.SharedMaterials.Length; v++)
187 {
188 Material m = null;
189
190if (outline.SharedMaterials[v].mainTexture != null && outline.SharedMaterials[v])
191 {
192foreach (Material g in materialBuffer)
193 {
194if (g.mainTexture == outline.SharedMaterials[v].mainTexture)
195 {
196if (aRenderer && g.color == lor)
197 m = g;
198el if (g.color == lor).color)
199 m = g;
200 }
201 }
202
203if (m == null)
204 {
205if (aRenderer)
206 m = new Material(outlineEraMaterial);
207el
208 m = new Material(lor));
209 m.mainTexture = outline.SharedMaterials[v].mainTexture;
210 materialBuffer.Add(m);
211 }
212 }
213el
小白兔怎么画214 {
215if (aRenderer)
216 m = outlineEraMaterial;
217el
218 m = lor);
219 }
220
221if (backfaceCulling)
222 m.SetInt("_Culling", (int)UnityEngine.Rendering.CullMode.Back);
223el
224 m.SetInt("_Culling", (int)UnityEngine.Rendering.CullMode.Off);
225
226 commandBuffer.DrawRenderer(outline.Renderer, m, 0, 0);
227 MeshFilter mL = outline.MeshFilter;
228if (mL)
229 {
230if (mL.sharedMesh != null)
231 {
232for (int i = 1; i < mL.sharedMesh.subMeshCount; i++)
233 commandBuffer.DrawRenderer(outline.Renderer, m, i, 0);
234 }
235 }
236 SkinnedMeshRenderer sMR = outline.SkinnedMeshRenderer;
238 {
239if (sMR.sharedMesh != null)
240 {
愤怒图片241for (int i = 1; i < sMR.sharedMesh.subMeshCount; i++)骆驼祥子感悟
242 commandBuffer.DrawRenderer(outline.Renderer, m, i, 0);
243 }
244 }
245 }
246 }
247 }
248
249 outlineCamera.Render();
250 }
251
252private void OnEnable()
253 {
254//if (autoEnableOutlines)
255//{
256// Outline[] o = FindObjectsOfType<Outline>();
257
258// foreach (Outline oL in o)
259// {
260// oL.enabled = fal;
261// oL.enabled = true;
262// }
263//}
264 }
265
266void OnDestroy()
267 {
268if (renderTexture != null)
269 renderTexture.Relea();
270if (extraRenderTexture != null)
271 extraRenderTexture.Relea();
272 DestroyMaterials();
预防煤气中毒273 }
274
275void OnRenderImage(RenderTexture source, RenderTexture destination)
276 {
277if (outlineShaderMaterial != null)
278 {
279 outlineShaderMaterial.SetTexture("_OutlineSource", renderTexture);
280
281if (addLinesBetweenColors)
282 {
283 Graphics.Blit(source, extraRenderTexture, outlineShaderMaterial, 0);
284 outlineShaderMaterial.SetTexture("_OutlineSource", extraRenderTexture);
285 }
286 Graphics.Blit(source, destination, outlineShaderMaterial, 1);
287 }
288 }
289
290private void CreateMaterialsIfNeeded()
291 {
292if (outlineShader == null)
293 outlineShader = Resources.Load<Shader>("Shaders/Outline/OutlineShader");
294if (outlineBufferShader == null)
295 {
296 outlineBufferShader = Resources.Load<Shader>("Shaders/Outline/OutlineBufferShader"); 297 }
298if (outlineShaderMaterial == null)
299 {
300 outlineShaderMaterial = new Material(outlineShader);
301 outlineShaderMaterial.hideFlags = HideFlags.HideAndDontSave;
302 UpdateMaterialsPublicProperties();
303 }
304if (outlineEraMaterial == null)
305 outlineEraMaterial = CreateMaterial(new Color(0, 0, 0, 0));
306if (outline1Material == null)
307 outline1Material = CreateMaterial(new Color(1, 0, 0, 0));
308if (outline2Material == null)
309 outline2Material = CreateMaterial(new Color(0, 1, 0, 0));
310if (outline3Material == null)
311 outline3Material = CreateMaterial(new Color(0, 0, 1, 0));
312if (outline4Material == null)
313 outline4Material = CreateMaterial(new Color(0, 0, 0, 1));
314 }
315
316private void DestroyMaterials()
317 {
318foreach (Material m in materialBuffer)
319 DestroyImmediate(m);
320 materialBuffer.Clear();
321 DestroyImmediate(outlineShaderMaterial);
322 DestroyImmediate(outlineEraMaterial);
323 DestroyImmediate(outline1Material);
324 DestroyImmediate(outline2Material);
325 DestroyImmediate(outline3Material);
327 outlineBufferShader = null;
328 outlineShaderMaterial = null;
329 outlineEraMaterial = null;
330 outline1Material = null;
331 outline2Material = null;
332 outline3Material = null;
333 outline4Material = null;
334 }
335
336public void UpdateMaterialsPublicProperties()
337 {
338if (outlineShaderMaterial)
339 {
340float scalingFactor = 1;
341if (scaleWithScreenSize)
342 {
小班找朋友教案343// If Screen.height gets bigger, outlines gets thicker
344 scalingFactor = Screen.height / 360.0f;
345 }
346
347// If scaling is too small (height less than 360 pixels), make sure you still render the outlines, but render them with 1 thickness
348if (scaleWithScreenSize && scalingFactor < 1)
349 {
350if (UnityEngine.XR.XRSettings.isDeviceActive && sourceCamera.stereoTargetEye != StereoTargetEyeMask.None)
351 {
352 outlineShaderMaterial.SetFloat("_LineThicknessX", (1 / 1000.0f) * (1.0f / UnityEngine.TextureWidth) * 1000.0f);
353 outlineShaderMaterial.SetFloat("_LineThicknessY", (1 / 1000.0f) * (1.0f / UnityEngine.TextureHeight) * 1000.0f);
354 }
355el
356 {
357 outlineShaderMaterial.SetFloat("_LineThicknessX", (1 / 1000.0f) * (1.0f / Screen.width) * 1000.0f);
358 outlineShaderMaterial.SetFloat("_LineThicknessY", (1 / 1000.0f) * (1.0f / Screen.height) * 1000.0f);
359 }
可爱熊猫图片360 }
361el
362 {
363if (UnityEngine.XR.XRSettings.isDeviceActive && sourceCamera.stereoTargetEye != StereoTargetEyeMask.None)
364 {
365 outlineShaderMaterial.SetFloat("_LineThicknessX", scalingFactor * (lineThickness / 1000.0f) * (1.0f / UnityEngine.TextureWidth) * 1000.0f); 366 outlineShaderMaterial.SetFloat("_LineThicknessY", scalingFactor * (lineThickness / 1000.0f) * (1.0f / UnityEngine.TextureHeight) * 1000.0f); 367 }
368el
369 {
370 outlineShaderMaterial.SetFloat("_LineThicknessX", scalingFactor * (lineThickness / 1000.0f) * (1.0f / Screen.width) * 1000.0f);
371 outlineShaderMaterial.SetFloat("_LineThicknessY", scalingFactor * (lineThickness / 1000.0f) * (1.0f / Screen.height) * 1000.0f);
372 }
373 }
374 outlineShaderMaterial.SetFloat("_LineIntensity", lineIntensity);
375 outlineShaderMaterial.SetFloat("_FillAmount", fillAmount);
376 outlineShaderMaterial.SetColor("_LineColor1", lineColor0 * lineColor0);
377 outlineShaderMaterial.SetColor("_LineColor2", lineColor1 * lineColor1);
378 outlineShaderMaterial.SetColor("_LineColor3", lineColor2 * lineColor2);
379 outlineShaderMaterial.SetColor("_LineColor4", lineColor3 * lineColor3);
380if (flipY)
381 outlineShaderMaterial.SetInt("_FlipY", 1);
382el
383 outlineShaderMaterial.SetInt("_FlipY", 0);
384if (!additiveRendering)
385 outlineShaderMaterial.SetInt("_Dark", 1);
386el
387 outlineShaderMaterial.SetInt("_Dark", 0);
388if (cornerOutlines)
389 outlineShaderMaterial.SetInt("_CornerOutlines", 1);
390el
391 outlineShaderMaterial.SetInt("_CornerOutlines", 0);
392
393 Shader.SetGlobalFloat("_OutlineAlphaCutoff", alphaCutoff);
394 }
395 }
396
397void UpdateOutlineCameraFromSource()
398 {
399 outlineCamera.CopyFrom(sourceCamera);
400 deringPath = RenderingPath.Forward;
401 outlineCamera.backgroundColor = new Color(0.0f, 0.0f, 0.0f, 0.0f);
402 outlineCamera.clearFlags = CameraClearFlags.SolidColor;
403 = new Rect(0, 0, 1, 1);
404 outlineCamera.cullingMask = 0;
405 outlineCamera.targetTexture = renderTexture;
406 abled = fal;
407#if UNITY_EDITOR
408 outlineCamera.allowHDR = fal;
409#el
410 outlineCamera.allowHDR = fal;
411#endif
412 }
413
414public void AddOutline(Outline outline)