最近学Shader有点心得,作了一个SLG画线模块。github地址:https://github.com/871041532/SLGDrawLinegit
性能有能再提升的地方,欢迎大佬指点。github
外部接口,只有两个:app
屡次调用画线效果:性能
using System.Collections.Generic; using UnityEngine; using LineHandle = System.Int32; class LineManager { private GameObject m_root = null; private GameObject m_origin = null; private Stack<GameObject> m_linePool = null; private Dictionary<int, GameObject> m_drawLines = null; private int m_index = 0; #region 外部接口 //参数:起始点、终止点、颜色、速度 public LineHandle DrawLine(Vector3 start,Vector3 end,Color color,float speed) { //从池中拿出 GameObject line = getFromPool(); Transform lineTransform = line.transform; Transform childTransform = lineTransform.GetChild(0); Mesh mesh = childTransform.GetComponent<MeshFilter>().mesh; var vertices = mesh.vertices; //设置颜色 var colors = new Color[vertices.Length]; for (int i = 0; i < colors.Length; i++) { colors[i] = color; } mesh.colors = colors; //设置父transform位置朝向,子transform缩放 Vector3 position = new Vector3((start.x+end.x)/2,(start.y+end.y)/2,(start.z+end.z)/2); Vector3 scale =new Vector3(1,Vector3.Distance(start,end),1); Vector3 direction = (end - start).normalized; lineTransform.localPosition = position; childTransform.localScale = scale; lineTransform.localRotation = Quaternion.LookRotation(direction); //设置Y轴缩放,速度值 var uv2 = new Vector2[vertices.Length]; for (int i = 0; i < uv2.Length; i++) { uv2[i] = new Vector2(childTransform.localScale.y / childTransform.localScale.x, speed); } mesh.uv2 = uv2; //放入字典 m_drawLines.Add(++m_index, line); return m_index; } //参数:索引 public void BackLine(LineHandle handle) { if(m_drawLines.ContainsKey(handle)) { GameObject line = m_drawLines[handle]; m_drawLines.Remove(handle); backToPool(line); } } #endregion #region 内部实现 private void Init() { m_origin = Resources.Load("DrawLine/Line") as GameObject; m_linePool = new Stack<GameObject>(23); m_root = new GameObject("LineRoot"); m_drawLines = new Dictionary<int, GameObject>(23); m_index = 0; } private GameObject getFromPool() { if (m_linePool.Count==0) { GameObject gameObject = GameObject.Instantiate(m_origin); gameObject.transform.parent = m_root.transform; return gameObject; } else { return m_linePool.Pop(); } } private void backToPool(GameObject line) { line.transform.localPosition = new Vector3(1000,1000,1000); m_linePool.Push(line); } #endregion #region singleton private static LineManager _instance = null; private LineManager() { Init(); } public static LineManager Instance { get { if (_instance==null) { _instance = new LineManager(); } return _instance; } private set { } } #endregion }
Shader "lineShader"{ Properties { _MainTex("Line Texture",2D) = "white"{} _ShowLength("Show Length",Float)=6.0 //展示的长度 _AlphaLength("Alpha Length",Float)=5.0 //有透明效果的长度 _AllShowLength("AllShow Length",Float)=10 //临界值,若是线比它短,那么全都显示 } SubShader{ Tags{ "Queue" = "AlphaTest" "IgnoreProjector" = "True" "RenderType" = "TransparentCutout" } Pass { Tags{ "LightMode" = "ForwardBase" } ZWrite Off Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #pragma vertex vert #pragma fragment frag #include "Lighting.cginc" sampler2D _MainTex; float4 _MainTex_ST; float _ShowLength; float _AlphaLength; float _AllShowLength; struct a2v { float4 vertex:POSITION; float4 texcoord:TEXCOORD0; fixed4 color:COLOR0; float2 uv2 : TEXCOORD1; //第二套UV:x份量存储y轴缩放,y份量存储滚动速度 }; struct v2f { float4 pos:SV_POSITION; float2 uv:TEXCOORD1; fixed4 color:COLOR1; float2 uv2:TEXCOORD2; //x份量存储Y轴缩放固定值,y份量存储滚动前uv.y }; v2f vert(a2v v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.uv.xy = TRANSFORM_TEX(v.texcoord,_MainTex); o.uv.y *=v.uv2.x;//Y轴缩放 o.color=v.color; o.uv2=o.uv; o.uv2.x=v.uv2.x; //o.uv2.x存储Y轴缩放固定值,y轴当前uv.y o.uv.y -=v.uv2.y* _Time.z; //Y轴随时间偏移 return o; } fixed4 frag(v2f i) :SV_Target { fixed4 color = tex2D(_MainTex,i.uv.xy); //后半段透明值与前半段透明值,取最大值 i.color.a=max(clamp((_ShowLength-(i.uv2.x-i.uv2.y))/_AlphaLength,0,1),clamp((_ShowLength-i.uv2.y)/_AlphaLength,0,1)); //i.uv2.y存储此片元的UV.y //当比_AllShowLength小的时候所有显示 i.color.a+=clamp(_AllShowLength-i.uv2.x,0,1); //大于0 i.color.a *= color.a; return i.color; } ENDCG } } //Fallback "VertexLit" }