关键词:
问题背景:
最近要实现选中实体的高亮效果,要那种类似于unity中Outline的效果,网格轮廓高亮效果。
效果图:
具体代码:
OutlineEffect.cs
实体高亮效果类:
轮廓边总控制类,该脚本需要挂载到场景相机上
1 using UnityEngine; 2 using System.Collections.Generic; 3 using UnityEngine.Rendering; 4 5 namespace Tx3d.Framework 6 7 [DisallowMultipleComponent] 8 [RequireComponent(typeof(Camera))] 9 [ExecuteInEditMode] 10 public class OutlineEffect : MonoBehaviour 11 12 public static OutlineEffect Instance get; private set; 13 14 private readonly LinkedSet<Outline> outlines = new LinkedSet<Outline>(); 15 16 [Range(1.0f, 6.0f)] 17 public float lineThickness = 1.0f; 18 [Range(0, 10)] 19 public float lineIntensity = 1.2f; 20 [Range(0, 1)] 21 public float fillAmount = 0.108f; 22 23 public Color lineColor0 = Color.yellow; 24 public Color lineColor1 = Color.green; 25 public Color lineColor2 = Color.blue; 26 public Color lineColor3 = Color.cyan; 27 28 public bool additiveRendering = false; 29 30 public bool backfaceCulling = true; 31 32 [Header("These settings can affect performance!")] 33 public bool cornerOutlines = false; 34 public bool addLinesBetweenColors = false; 35 36 [Header("Advanced settings")] 37 public bool scaleWithScreenSize = true; 38 [Range(0.1f, .9f)] 39 public float alphaCutoff = .5f; 40 public bool flipY = false; 41 public Camera sourceCamera; 42 public bool autoEnableOutlines = true; 43 44 [HideInInspector] 45 public Camera outlineCamera; 46 Material outline1Material; 47 Material outline2Material; 48 Material outline3Material; 49 Material outline4Material; 50 Material outlineEraseMaterial; 51 Shader outlineShader; 52 Shader outlineBufferShader; 53 [HideInInspector] 54 public Material outlineShaderMaterial; 55 [HideInInspector] 56 public RenderTexture renderTexture; 57 [HideInInspector] 58 public RenderTexture extraRenderTexture; 59 60 CommandBuffer commandBuffer; 61 62 Material GetMaterialFromID(int ID) 63 64 if (ID == 0) 65 return outline1Material; 66 else if (ID == 1) 67 return outline2Material; 68 else if (ID == 2) 69 return outline3Material; 70 else if (ID == 3) 71 return outline4Material; 72 else 73 return 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; 87 return m; 88 89 90 private void Awake() 91 92 if (Instance != null) 93 94 Destroy(this); 95 throw new System.Exception("you can only have one outline camera in the scene"); 96 97 98 Instance = this; 99 100 101 void Start() 102 103 CreateMaterialsIfNeeded(); 104 UpdateMaterialsPublicProperties(); 105 106 if (sourceCamera == null) 107 108 sourceCamera = GetComponent<Camera>(); 109 110 if (sourceCamera == null) 111 sourceCamera = Camera.main; 112 113 114 if (outlineCamera == null) 115 116 foreach (Camera c in GetComponentsInChildren<Camera>()) 117 118 if (c.name == "Outline Camera") 119 120 outlineCamera = c; 121 c.enabled = false; 122 123 break; 124 125 126 127 if (outlineCamera == null) 128 129 GameObject cameraGameObject = new GameObject("Outline Camera"); 130 cameraGameObject.transform.parent = sourceCamera.transform; 131 outlineCamera = cameraGameObject.AddComponent<Camera>(); 132 outlineCamera.enabled = false; 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 144 bool RenderTheNextFrame; 145 public void OnPreRender() 146 147 if (commandBuffer == null) 148 return; 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 152 if (outlines.Count == 0) 153 154 if (!RenderTheNextFrame) 155 return; 156 157 RenderTheNextFrame = false; 158 159 else 160 161 RenderTheNextFrame = true; 162 163 164 CreateMaterialsIfNeeded(); 165 166 if (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.pixelHeight, 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 179 foreach (Outline outline in outlines) 180 181 LayerMask l = sourceCamera.cullingMask; 182 183 // if (outline != null && l == (l | (1 << outline.gameObject.layer))) 184 if (outline != null) 185 186 for (int v = 0; v < outline.SharedMaterials.Length; v++) 187 188 Material m = null; 189 190 if (outline.SharedMaterials[v].mainTexture != null && outline.SharedMaterials[v]) 191 192 foreach (Material g in materialBuffer) 193 194 if (g.mainTexture == outline.SharedMaterials[v].mainTexture) 195 196 if (outline.eraseRenderer && g.color == outlineEraseMaterial.color) 197 m = g; 198 else if (g.color == GetMaterialFromID(outline.color).color) 199 m = g; 200 201 202 203 if (m == null) 204 205 if (outline.eraseRenderer) 206 m = new Material(outlineEraseMaterial); 207 else 208 m = new Material(GetMaterialFromID(outline.color)); 209 m.mainTexture = outline.SharedMaterials[v].mainTexture; 210 materialBuffer.Add(m); 211 212 213 else 214 215 if (outline.eraseRenderer) 216 m = outlineEraseMaterial; 217 else 218 m = GetMaterialFromID(outline.color); 219 220 221 if (backfaceCulling) 222 m.SetInt("_Culling", (int)UnityEngine.Rendering.CullMode.Back); 223 else 224 m.SetInt("_Culling", (int)UnityEngine.Rendering.CullMode.Off); 225 226 commandBuffer.DrawRenderer(outline.Renderer, m, 0, 0); 227 MeshFilter mL = outline.MeshFilter; 228 if (mL) 229 230 if (mL.sharedMesh != null) 231 232 for (int i = 1; i < mL.sharedMesh.subMeshCount; i++) 233 commandBuffer.DrawRenderer(outline.Renderer, m, i, 0); 234 235 236 SkinnedMeshRenderer sMR = outline.SkinnedMeshRenderer; 237 if (sMR) 238 239 if (sMR.sharedMesh != null) 240 241 for (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 252 private void OnEnable() 253 254 //if (autoEnableOutlines) 255 // 256 // Outline[] o = FindObjectsOfType<Outline>(); 257 258 // foreach (Outline oL in o) 259 // 260 // oL.enabled = false; 261 // oL.enabled = true; 262 // 263 // 264 265 266 void OnDestroy() 267 268 if (renderTexture != null) 269 renderTexture.Release(); 270 if (extraRenderTexture != null) 271 extraRenderTexture.Release(); 272 DestroyMaterials(); 273 274 275 void OnRenderImage(RenderTexture source, RenderTexture destination) 276 277 if (outlineShaderMaterial != null) 278 279 outlineShaderMaterial.SetTexture("_OutlineSource", renderTexture); 280 281 if (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 290 private void CreateMaterialsIfNeeded() 291 292 if (outlineShader == null) 293 outlineShader = Resources.Load<Shader>("Shaders/Outline/OutlineShader"); 294 if (outlineBufferShader == null) 295 296 outlineBufferShader = Resources.Load<Shader>("Shaders/Outline/OutlineBufferShader"); 297 298 if (outlineShaderMaterial == null) 299 300 outlineShaderMaterial = new Material(outlineShader); 301 outlineShaderMaterial.hideFlags = HideFlags.HideAndDontSave; 302 UpdateMaterialsPublicProperties(); 303 304 if (outlineEraseMaterial == null) 305 outlineEraseMaterial = CreateMaterial(new Color(0, 0, 0, 0)); 306 if (outline1Material == null) 307 outline1Material = CreateMaterial(new Color(1, 0, 0, 0)); 308 if (outline2Material == null) 309 outline2Material = CreateMaterial(new Color(0, 1, 0, 0)); 310 if (outline3Material == null) 311 outline3Material = CreateMaterial(new Color(0, 0, 1, 0)); 312 if (outline4Material == null) 313 outline4Material = CreateMaterial(new Color(0, 0, 0, 1)); 314 315 316 private void DestroyMaterials() 317 318 foreach (Material m in materialBuffer) 319 DestroyImmediate(m); 320 materialBuffer.Clear(); 321 DestroyImmediate(outlineShaderMaterial); 322 DestroyImmediate(outlineEraseMaterial); 323 DestroyImmediate(outline1Material); 324 DestroyImmediate(outline2Material); 325 DestroyImmediate(outline3Material); 326 outlineShader = null; 327 outlineBufferShader = null; 328 outlineShaderMaterial = null; 329 outlineEraseMaterial = null; 330 outline1Material = null; 331 outline2Material = null; 332 outline3Material = null; 333 outline4Material = null; 334 335 336 public void UpdateMaterialsPublicProperties() 337 338 if (outlineShaderMaterial) 339 340 float scalingFactor = 1; 341 if (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 348 if (scaleWithScreenSize && scalingFactor < 1) 349 350 if (UnityEngine.XR.XRSettings.isDeviceActive && sourceCamera.stereoTargetEye != StereoTargetEyeMask.None) 351 352 outlineShaderMaterial.SetFloat("_LineThicknessX", (1 / 1000.0f) * (1.0f / UnityEngine.XR.XRSettings.eyeTextureWidth) * 1000.0f); 353 outlineShaderMaterial.SetFloat("_LineThicknessY", (1 / 1000.0f) * (1.0f / UnityEngine.XR.XRSettings.eyeTextureHeight) * 1000.0f); 354 355 else 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 361 else 362 363 if (UnityEngine.XR.XRSettings.isDeviceActive && sourceCamera.stereoTargetEye != StereoTargetEyeMask.None) 364 365 outlineShaderMaterial.SetFloat("_LineThicknessX", scalingFactor * (lineThickness / 1000.0f) * (1.0f / UnityEngine.XR.XRSettings.eyeTextureWidth) * 1000.0f); 366 outlineShaderMaterial.SetFloat("_LineThicknessY", scalingFactor * (lineThickness / 1000.0f) * (1.0f / UnityEngine.XR.XRSettings.eyeTextureHeight) * 1000.0f); 367 368 else 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); 380 if (flipY) 381 outlineShaderMaterial.SetInt("_FlipY", 1); 382 else 383 outlineShaderMaterial.SetInt("_FlipY", 0); 384 if (!additiveRendering) 385 outlineShaderMaterial.SetInt("_Dark", 1); 386 else 387 outlineShaderMaterial.SetInt("_Dark", 0); 388 if (cornerOutlines) 389 outlineShaderMaterial.SetInt("_CornerOutlines", 1); 390 else 391 outlineShaderMaterial.SetInt("_CornerOutlines", 0); 392 393 Shader.SetGlobalFloat("_OutlineAlphaCutoff", alphaCutoff); 394 395 396 397 void UpdateOutlineCameraFromSource() 398 399 outlineCamera.CopyFrom(sourceCamera); 400 outlineCamera.renderingPath = RenderingPath.Forward; 401 outlineCamera.backgroundColor = new Color(0.0f, 0.0f, 0.0f, 0.0f); 402 outlineCamera.clearFlags = CameraClearFlags.SolidColor; 403 outlineCamera.rect = new Rect(0, 0, 1, 1); 404 outlineCamera.cullingMask = 0; 405 outlineCamera.targetTexture = renderTexture; 406 outlineCamera.enabled = false; 407 #if UNITY_EDITOR 408 outlineCamera.allowHDR = false; 409 #else 410 outlineCamera.allowHDR = false; 411 #endif 412 413 414 public void AddOutline(Outline outline) 415 => outlines.Add(outline); 416 417 public void RemoveOutline(Outline outline) 418 => outlines.Remove(outline); 419 420
LinkedSet.cs
实体高亮效果的集合相关逻辑类:
辅助OutlineEffect类
1 using System; 2 using System.Collections.Generic; 3 4 namespace Tx3d 5 6 /// <summary> 7 /// 具有列表的快速迭代时间、无重复和快速删除/包含HashSet时间的集合。 8 /// </summary> 9 public class LinkedSet<T> : IEnumerable<T> 10 11 private LinkedList<T> list; 12 private Dictionary<T, LinkedListNode<T>> dictionary; 13 14 public LinkedSet() 15 16 list = new LinkedList<T>(); 17 dictionary = new Dictionary<T, LinkedListNode<T>>(); 18 19 20 public LinkedSet(IEqualityComparer<T> comparer) 21 22 list = new LinkedList<T>(); 23 dictionary = new Dictionary<T, LinkedListNode<T>>(comparer); 24 25 26 /// <summary> 27 /// 如果项在LinkedSet中不存在,则返回true 28 /// </summary> 29 public bool Add(T t) 30 31 if (dictionary.ContainsKey(t)) 32 return false; 33 34 LinkedListNode<T> node = list.AddLast(t); 35 dictionary.Add(t, node); 36 return true; 37 38 39 /// <summary> 40 /// 如果项之前确实存在于LinkedSet中,则返回true 41 /// </summary> 42 public bool Remove(T t) 43 44 LinkedListNode<T> node; 45 46 if (dictionary.TryGetValue(t, out node)) 47 48 dictionary.Remove(t); 49 list.Remove(node); 50 return true; 51 52 else 53 54 return false; 55 56 57 58 public void Clear() 59 60 list.Clear(); 61 dictionary.Clear(); 62 63 64 public bool Contains(T t) 65 => dictionary.ContainsKey(t); 66 67 public int Count 68 => list.Count; 69 70 public IEnumerator<T> GetEnumerator() 71 => list.GetEnumerator(); 72 73 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 74 => list.GetEnumerator(); 75 76
Outline.cs
外边框高亮基本信息类:
该信息类需要的mesh渲染器所在的物体上的信息(谁有MeshRenderer和MeshFilter物体的信息)
1 /// <summary> 2 /// 外边高亮基本信息类 3 /// </summary> 4 public class Outline 5 6 public Renderer Renderer get; set; 7 public SkinnedMeshRenderer SkinnedMeshRenderer get; set; 8 public MeshFilter MeshFilter get; set; 9 10 public int color; 11 public bool eraseRenderer; 12 13 private Material[] _SharedMaterials; 14 public Material[] SharedMaterials 15 16 get 17 18 if (_SharedMaterials == null) 19 _SharedMaterials = Renderer.sharedMaterials; 20 21 return _SharedMaterials; 22 23 24
OutlineEffect.shader
计算所需要的shader
1 Shader "Hidden/OutlineEffect" 2 3 Properties 4 5 _MainTex ("Base (RGB)", 2D) = "white" 6 7 8 SubShader 9 10 Pass 11 12 Tags "RenderType" = "Opaque" 13 LOD 200 14 ZTest Always 15 ZWrite Off 16 Cull Off 17 18 CGPROGRAM 19 20 #pragma vertex vert 21 #pragma fragment frag 22 #pragma target 3.0 23 #include "UnityCG.cginc" 24 25 sampler2D _MainTex; 26 float4 _MainTex_ST; 27 sampler2D _OutlineSource; 28 29 struct v2f 30 31 float4 position : SV_POSITION; 32 float2 uv : TEXCOORD0; 33 ; 34 35 v2f vert(appdata_img v) 36 37 v2f o; 38 o.position = UnityObjectToClipPos(v.vertex); 39 o.uv = v.texcoord; 40 41 return o; 42 43 44 float _LineThicknessX; 45 float _LineThicknessY; 46 int _FlipY; 47 uniform float4 _MainTex_TexelSize; 48 49 half4 frag(v2f input) : COLOR 50 51 float2 uv = input.uv; 52 if (_FlipY == 1) 53 uv.y = uv.y; 54 #if UNITY_UV_STARTS_AT_TOP 55 if (_MainTex_TexelSize.y < 0) 56 uv.y = 1 - uv.y; 57 #endif 58 59 //half4 originalPixel = tex2D(_MainTex,input.uv, UnityStereoScreenSpaceUVAdjust(input.uv, _MainTex_ST)); 60 half4 outlineSource = tex2D(_OutlineSource, UnityStereoScreenSpaceUVAdjust(uv, _MainTex_ST)); 61 62 const float h = .95f; 63 64 half4 sample1 = tex2D(_OutlineSource, uv + float2(_LineThicknessX,0.0)); 65 half4 sample2 = tex2D(_OutlineSource, uv + float2(-_LineThicknessX,0.0)); 66 half4 sample3 = tex2D(_OutlineSource, uv + float2(.0,_LineThicknessY)); 67 half4 sample4 = tex2D(_OutlineSource, uv + float2(.0,-_LineThicknessY)); 68 69 bool red = sample1.r > h || sample2.r > h || sample3.r > h || sample4.r > h; 70 bool green = sample1.g > h || sample2.g > h || sample3.g > h || sample4.g > h; 71 bool blue = sample1.b > h || sample2.b > h || sample3.b > h || sample4.b > h; 72 73 if ((red && blue) || (green && blue) || (red && green)) 74 return float4(0,0,0,0); 75 else 76 return outlineSource; 77 78 79 ENDCG 80 81 82 Pass 83 84 Tags "RenderType"="Opaque" 85 LOD 200 86 ZTest Always 87 ZWrite Off 88 Cull Off 89 90 CGPROGRAM 91 92 #pragma vertex vert 93 #pragma fragment frag 94 #pragma target 3.0 95 #include "UnityCG.cginc" 96 97 sampler2D _MainTex; 98 float4 _MainTex_ST; 99 sampler2D _OutlineSource; 100 101 struct v2f 102 float4 position : SV_POSITION; 103 float2 uv : TEXCOORD0; 104 ; 105 106 v2f vert(appdata_img v) 107 108 v2f o; 109 o.position = UnityObjectToClipPos(v.vertex); 110 o.uv = v.texcoord; 111 112 return o; 113 114 115 float _LineThicknessX; 116 float _LineThicknessY; 117 float _LineIntensity; 118 half4 _LineColor1; 119 half4 _LineColor2; 120 half4 _LineColor3; 121 half4 _LineColor4; 122 int _FlipY; 123 int _Dark; 124 float _FillAmount; 125 int _CornerOutlines; 126 uniform float4 _MainTex_TexelSize; 127 128 half4 frag (v2f input) : COLOR 129 130 float2 uv = input.uv; 131 if (_FlipY == 1) 132 uv.y = 1 - uv.y; 133 #if UNITY_UV_STARTS_AT_TOP 134 if (_MainTex_TexelSize.y < 0) 135 uv.y = 1 - uv.y; 136 #endif 137 138 half4 originalPixel = tex2D(_MainTex, UnityStereoScreenSpaceUVAdjust(input.uv, _MainTex_ST)); 139 half4 outlineSource = tex2D(_OutlineSource, UnityStereoScreenSpaceUVAdjust(uv, _MainTex_ST)); 140 141 const float h = .95f; 142 half4 outline = 0; 143 bool hasOutline = false; 144 145 half4 sample1 = tex2D(_OutlineSource, uv + float2(_LineThicknessX,0.0)); 146 half4 sample2 = tex2D(_OutlineSource, uv + float2(-_LineThicknessX,0.0)); 147 half4 sample3 = tex2D(_OutlineSource, uv + float2(.0,_LineThicknessY)); 148 half4 sample4 = tex2D(_OutlineSource, uv + float2(.0,-_LineThicknessY)); 149 150 bool outside = outlineSource.a < h; 151 bool outsideDark = outside && _Dark; 152 153 if (_CornerOutlines) 154 155 // TODO: Conditional compile 156 half4 sample5 = tex2D(_OutlineSource, uv + float2(_LineThicknessX, _LineThicknessY)); 157 half4 sample6 = tex2D(_OutlineSource, uv + float2(-_LineThicknessX, -_LineThicknessY)); 158 half4 sample7 = tex2D(_OutlineSource, uv + float2(_LineThicknessX, -_LineThicknessY)); 159 half4 sample8 = tex2D(_OutlineSource, uv + float2(-_LineThicknessX, _LineThicknessY)); 160 161 if (sample1.r > h || sample2.r > h || sample3.r > h || sample4.r > h || 162 sample5.r > h || sample6.r > h || sample7.r > h || sample8.r > h) 163 164 outline = _LineColor1 * _LineIntensity * _LineColor1.a; 165 if (outsideDark) 166 originalPixel *= 1 - _LineColor1.a; 167 hasOutline = true; 168 169 else if (sample1.g > h || sample2.g > h || sample3.g > h || sample4.g > h || 170 sample5.g > h || sample6.g > h || sample7.g > h || sample8.g > h) 171 172 outline = _LineColor2 * _LineIntensity * _LineColor2.a; 173 if (outsideDark) 174 originalPixel *= 1 - _LineColor2.a; 175 hasOutline = true; 176 177 else if (sample1.b > h || sample2.b > h || sample3.b > h || sample4.b > h || 178 sample5.b > h || sample6.b > h || sample7.b > h || sample8.b > h) 179 180 outline = _LineColor3 * _LineIntensity * _LineColor3.a; 181 if (outsideDark) 182 originalPixel *= 1 - _LineColor3.a; 183 hasOutline = true; 184 185 else if (sample1.a > h || sample2.a > h || sample3.a > h || sample4.a > h || 186 sample5.a > h || sample6.a > h || sample7.a > h || sample8.a > h) 187 188 outline = _LineColor4 * _LineIntensity * _LineColor4.a; 189 if (outsideDark) 190 originalPixel *= 1 - _LineColor4.a; 191 hasOutline = true; 192 193 194 if (!outside) 195 outline *= _FillAmount; 196 197 else 198 199 if (sample1.r > h || sample2.r > h || sample3.r > h || sample4.r > h) 200 201 outline = _LineColor1 * _LineIntensity * _LineColor1.a; 202 if (outsideDark) 203 originalPixel *= 1 - _LineColor1.a; 204 hasOutline = true; 205 206 else if (sample1.g > h || sample2.g > h || sample3.g > h || sample4.g > h) 207 208 outline = _LineColor2 * _LineIntensity * _LineColor2.a; 209 if (outsideDark) 210 originalPixel *= 1 - _LineColor2.a; 211 hasOutline = true; 212 213 else if (sample1.b > h || sample2.b > h || sample3.b > h || sample4.b > h) 214 215 outline = _LineColor3 * _LineIntensity * _LineColor3.a; 216 if (outsideDark) 217 originalPixel *= 1 - _LineColor3.a; 218 hasOutline = true; 219 220 else if (sample1.a > h || sample2.a > h || sample3.a > h || sample4.a > h) 221 222 outline = _LineColor4 * _LineIntensity * _LineColor4.a; 223 if (outsideDark) 224 originalPixel *= 1 - _LineColor4.a; 225 hasOutline = true; 226 227 228 if (!outside) 229 outline *= _FillAmount; 230 231 232 //return outlineSource; 233 if (hasOutline) 234 return lerp(originalPixel + outline, outline, _FillAmount); 235 else 236 return originalPixel; 237 238 239 ENDCG 240 241 242 243 FallBack "Diffuse" 244
OutlineBufferEffect.shader
计算所需要的shader
1 Shader "Hidden/OutlineBufferEffect" 2 Properties 3 4 [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" 5 _Color ("Tint", Color) = (1,1,1,1) 6 [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0 7 8 9 SubShader 10 11 Tags 12 13 "Queue" = "Transparent" 14 "IgnoreProjector" = "True" 15 "RenderType" = "Transparent" 16 "PreviewType" = "Plane" 17 "CanUseSpriteAtlas" = "True" 18 19 20 // Change this stuff in OutlineEffect.cs instead! 21 //ZWrite Off 22 //Blend One OneMinusSrcAlpha 23 Cull [_Culling] 24 Lighting Off 25 26 CGPROGRAM 27 28 #pragma surface surf Lambert vertex:vert nofog noshadow noambient nolightmap novertexlights noshadowmask nometa //keepalpha 29 #pragma multi_compile _ PIXELSNAP_ON 30 31 sampler2D _MainTex; 32 fixed4 _Color; 33 float _OutlineAlphaCutoff; 34 35 struct Input 36 37 float2 uv_MainTex; 38 //fixed4 color; 39 ; 40 41 void vert(inout appdata_full v, out Input o) 42 43 #if defined(PIXELSNAP_ON) 44 v.vertex = UnityPixelSnap(v.vertex); 45 #endif 46 47 UNITY_INITIALIZE_OUTPUT(Input, o); 48 //o.color = v.color; 49 50 51 void surf(Input IN, inout SurfaceOutput o) 52 53 fixed4 c = tex2D(_MainTex, IN.uv_MainTex);// * IN.color; 54 if (c.a < _OutlineAlphaCutoff) discard; 55 56 float alpha = c.a * 99999999; 57 58 o.Albedo = _Color * alpha; 59 o.Alpha = alpha; 60 o.Emission = o.Albedo; 61 62 63 ENDCG 64 65 66 Fallback "Transparent/VertexLit" 67
//测试代码
其中outline是上面的信息对象,通过OutlineEffect中的AddOutline函数以及 RemoveOutline函数对场景物体进行管理,将需要高亮的物体的mesh信息构建的基本信息类并使用AddOutline函数添加进去,才可以实现高亮,取消高亮即调用RemoveOutline移除取消高亮物体的信息
1 // 实体是否高亮 2 public bool Highlight 3 4 get => highlight; 5 set 6 7 highlight = value; 8 9 if (highlight) 10 11 if (gameObject != null) 12 13 outline = outline ?? new Outline(); 14 outline.Renderer = gameObject.GetComponent<Renderer>(); 15 outline.MeshFilter = gameObject.GetComponent<MeshFilter>(); 16 outline.SkinnedMeshRenderer = gameObject.GetComponent<SkinnedMeshRenderer>(); 17 OutlineEffect.Instance?.AddOutline(outline); 18 19 20 else 21 22 OutlineEffect.Instance?.RemoveOutline(outline); 23 24 25
ok,实现了,但是这里的shader是摘得,因为我还在shader的学习阶段,记录下功能吧也算是
unity中实现ui渐变(代码片段)
一:效果演示二:使用TopColor:顶部颜色BottomColor:底部颜色三:代码实现usingSystem.Collections.Generic;usingUnityEngine;usingUnityEngine.UI;[DisallowMultipleComponent][AddComponentMenu("L 查看详情
unity中实现多层血条(代码片段)
一:效果演示二:使用——面板参数设置HpSlider:Slider组件TopBar:顶部血条DownBar:底部血条LastBarColor:最后一条血条的颜色T:血量改变时缓动的插值(如果不需要缓动效果则设置为1即可)——常规使用创... 查看详情
详解css中的网格布局,小程序中实现预约列表功能(代码片段)
随着这几年小程序的普及,我们去医院看病已经可以完全在小程序里完成,包括预约挂号、就诊、查验报告、缴费等。本篇就利用网格布局来实现一下医生的列表功能,先看一下实际完成的效果布局规划我们拿到效果... 查看详情
详解css中的网格布局,小程序中实现预约列表功能(代码片段)
随着这几年小程序的普及,我们去医院看病已经可以完全在小程序里完成,包括预约挂号、就诊、查验报告、缴费等。本篇就利用网格布局来实现一下医生的列表功能,先看一下实际完成的效果布局规划我们拿到效果... 查看详情
unity中实现ui描边(代码片段)
一:效果演示 二:使用MaterialPath:材质路径(需要自己创建材质并设置Shader为UI/Outline)OutlineColor:描边颜色OutlineWidth:描边宽度三:为什么尽量避免使用UGUI的Outline和Shadaw组件 UGUI源码解析——ShadowUGUI源码... 查看详情
unity中实现雷达图(代码片段)
一:效果演示二:实现思路——描边思路:一开始觉得这很简单,就直接绘制一个比当前大一圈的雷达图就可以了,试了试发现并没有那么简单当每个顶点的权重都相同时,也就是雷达图为正多边形时绘制... 查看详情
unity中实现雷达图(代码片段)
一:效果演示二:实现思路——描边思路:一开始觉得这很简单,就直接绘制一个比当前大一圈的雷达图就可以了,试了试发现并没有那么简单当每个顶点的权重都相同时,也就是雷达图为正多边形时绘制... 查看详情
unity3d日常开发unity3d中实现箭头指向目标点的效果(代码片段)
推荐阅读CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客QQ群:1040082875大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。一、前言最近开发的时候遇到了... 查看详情
游戏开发实战教你在unity中实现模型消融化为灰烬飘散的效果(shadergraph|消融|粒子系统|特效)(代码片段)
文章目录一、前言二、ShaderGraph环境准备三、模型准备:原神角色模型四、实现思路1、效果一的实现思路2、效果二的实现思路五、ShaderGraph具体实现1、效果一1.1、创建UnlitShaderGraph1.2、获取顶点坐标的y轴坐标1.3、滑块控制1.4... 查看详情
游戏开发小技unity中实现dota里的角色技能地面贴花效果(urp|shadergraph|decal)(代码片段)
本文最终效果文章目录一、前言二、环境准备1、URP环境准备2、技能范围图案二、方案一:写Shader实现1、Shader脚本:UrpDecal.shader2、材质球3、创建Cube4、地面场景5、添加RendererFeature:Decal6、移动DecalCube,与地面交叉7、... 查看详情
游戏开发小技unity中实现dota里的角色技能地面贴花效果(urp|shadergraph|decal)(代码片段)
本文最终效果文章目录一、前言二、环境准备1、URP环境准备2、技能范围图案二、方案一:写Shader实现1、Shader脚本:UrpDecal.shader2、材质球3、创建Cube4、地面场景5、添加RendererFeature:Decal6、移动DecalCube,与地面交叉7、... 查看详情
unity中实现限制recttransform下某个属性不可被修改(代码片段)
一:效果演示让RectTransform下某些属性不可以在Inspector面板上修改二:代码实现usingUnityEngine;publicclassTest:MonoBehaviourstaticDrivenRectTransformTrackertracker=newDrivenRectTransformTracker();privatevoidAwake()tracker.Clear();tracker.Add(gameObject,gameObje... 查看详情
unity中实现限制recttransform下某个属性不可被修改(代码片段)
一:效果演示让RectTransform下某些属性不可以在Inspector面板上修改二:代码实现usingUnityEngine;publicclassTest:MonoBehaviourstaticDrivenRectTransformTrackertracker=newDrivenRectTransformTracker();privatevoidAwake()tracker.Clear();tracker.Add(gameObject,gameObje... 查看详情
spine在unity中实现闪白效果
游戏开发过程中需要游戏对象被攻击的时候变白,然后有有闪烁的效果。这其实是两个效果:1.变白的效果要实现这个效果需要修改spine的shader模式。spine导入unity中时默认采用的shader是“Spine/Skeleton”需要将这个模式该为“Spine/Sk... 查看详情
unity中实现ui渐变(代码片段)
一:效果演示二:使用GradientDir:渐变方向ColorArray:颜色数组三:实现原理通过添加顶点并设置顶点数据实现渐变,注意颜色数组数量越多顶点和三角形数量也会增加UGUI源码解析——BaseMeshEffect四:代... 查看详情
在unity2020urp版本中实现lensflare功能(代码片段)
这个官方里面没有支持,只能自己去解决。效果请查看地址:https://www.bilibili.com/video/BV1w24y1o7pY/下面说一下我的实现过程。找来找去,我找到了一篇不错的解决方案,还带源码:http://warmcat.org/chai/blog/?p=5279... 查看详情
在unity中实现分页扩展(旋转3d)功能(ugui)(代码片段)
这次给大家介绍一个看起来是3D的效果的UI的切换在实际应用中别看起来不是那么呆板我们要首先创建两个Image通过修改point的位置来改变旋转的轴我们可以看到有两个模块是两个不同的方向的旋转我们分别把两块的pivot分别设为... 查看详情
如何在unity中实现拖尾效果
在制作游戏过程中会出现鼠标滑动的实现,而为啦增强视觉效果,往往会添加拖尾或者鼠标点击的特效,接下来就说说在unity中如何实现拖尾效果,首先unity中有个组件,叫TrailRenderer,在Component——>Effect——>TrailR... 查看详情