Unity UGUI 文字描边与渐变
文字描边
OutLine
默认顶点数为16
将描边距离分别设置x=100,y=50,使用OutLine8 与禁用OutLine8 对比,如下图,顶点数(Verts)相差100
一个字=一张图=2个三角面=6个顶点(vertex)包括2个共用顶点
使用Text,一个文字对应4个顶点,其中2个顶点共用
使用OutLine8,相当于在Text文本后面多绘制了8个文本,此时顶点数=2*6*9=108
Outline8 Code
using System.Collections.Generic;
using UGUIExtentions;
namespace UnityEngine.UI
{
/// <summary>
/// Adds an outline to a graphic using IVertexModifier.
/// </summary>
public class Outline8 : BaseMeshEffect
{
[SerializeField]
private Color m_EffectColor = new Color(0f, 0f, 0f, 1f);
[SerializeField]
private Vector2 m_EffectDistance = new Vector2(1f, -1f);
[SerializeField]
private bool m_UseGraphicAlpha = true;
private const float kMaxEffectDistance = 600f;
protected Outline8()
{ }
#if UNITY_EDITOR
protected override void OnValidate()
{
effectDistance = m_EffectDistance;
base.OnValidate();
}
#endif
/// <summary>
/// Color for the effect
/// </summary>
public Color effectColor
{
get { return m_EffectColor; }
set
{
m_EffectColor = value;
if (graphic != null)
graphic.SetVerticesDirty();
}
}
/// <summary>
/// How far is the shadow from the graphic.
/// </summary>
public Vector2 effectDistance
{
get { return m_EffectDistance; }
set
{
Mathf.Clamp(value.x, -kMaxEffectDistance, kMaxEffectDistance);
Mathf.Clamp(value.y, -kMaxEffectDistance, kMaxEffectDistance);
if (m_EffectDistance == value)
return;
m_EffectDistance = value;
if (graphic != null)
graphic.SetVerticesDirty();
}
}
/// <summary>
/// Should the shadow inherit the alpha from the graphic?
/// </summary>
public bool useGraphicAlpha
{
get { return m_UseGraphicAlpha; }
set
{
m_UseGraphicAlpha = value;
if (graphic != null)
graphic.SetVerticesDirty();
}
}
// 添加4个角的顶点
public override void ModifyMesh(VertexHelper vh)
{
if (!IsActive())
return;
var verts = ListPool<UIVertex>.Get();
vh.GetUIVertexStream(verts);
var neededCpacity = verts.Count * 5;
if (verts.Capacity < neededCpacity)
verts.Capacity = neededCpacity;
// 顶点部分 开始
var start = 0;
var end = verts.Count;
ApplyShadowZeroAlloc(verts, effectColor, start, verts.Count, effectDistance.x, effectDistance.y);
start = end;
end = verts.Count;
ApplyShadowZeroAlloc(verts, effectColor, start, verts.Count, effectDistance.x, -effectDistance.y);
start = end;
end = verts.Count;
ApplyShadowZeroAlloc(verts, effectColor, start, verts.Count, -effectDistance.x, effectDistance.y);
start = end;
end = verts.Count;
ApplyShadowZeroAlloc(verts, effectColor, start, verts.Count, -effectDistance.x, -effectDistance.y);
start = end;
end = verts.Count;
ApplyShadowZeroAlloc(verts, effectColor, start, verts.Count, effectDistance.x, 0);
start = end;
end = verts.Count;
ApplyShadowZeroAlloc(verts, effectColor, start, verts.Count, -effectDistance.x, 0);
start = end;
end = verts.Count;
ApplyShadowZeroAlloc(verts, effectColor, start, verts.Count, 0, effectDistance.y);
start = end;
end = verts.Count;
ApplyShadowZeroAlloc(verts, effectColor, start, verts.Count, 0, -effectDistance.y);
// 顶点部分 结束
// 顶点部分 优化写法
// 参考 https://github.com/n-yoda/unity-vertex-effects
/*var original = verts.Count;
var count = 0;
for (int x = -1; x <= 1; x++)
{
for (int y = -1; y <= 1; y++)
{
if (!(x == 0 && y == 0))
{
var next = count + original;
ApplyShadowZeroAlloc(verts, effectColor, count, next, effectDistance.x * x, effectDistance.y * y);
count = next;
}
}
}*/
vh.Clear();
vh.AddUIVertexTriangleStream(verts);
ListPool<UIVertex>.Release(verts);
}
protected void ApplyShadowZeroAlloc(List<UIVertex> verts, Color32 color, int start, int end, float x, float y)
{
UIVertex vt;
var neededCapacity = verts.Count + end - start;
if (verts.Capacity < neededCapacity)
verts.Capacity = neededCapacity;
for (int i = start; i < end; ++i)
{
vt = verts[i];
verts.Add(vt);
Vector3 v = vt.position;
v.x += x;
v.y += y;
vt.position = v;
var newColor = color;
if (m_UseGraphicAlpha)
newColor.a = (byte)((newColor.a * verts[i].color.a) / 255);
vt.color = newColor;
verts[i] = vt;
}
}
}
}
Text扩展
创建OutlineText继承Text,重写OnPopulateMesh,在内部进行描边
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class OutLineText : Text {
public bool m_OutLine=true;
public Color m_OutLineColor=Color.black;
public float m_OutLineOffsetX=0f;
public float m_OutLineOffsetY=0f;
protected override void OnPopulateMesh(VertexHelper toFill)
{
//这里是直接复制的UGUI的Text生成定点的代码
Vector2 extent=rectTransform.rect.size;
var settings= GetGenerationSettings(extent);
cachedTextGenerator.Populate(this.text, settings);
Rect inputRect = rectTransform.rect;
// get the text alignment anchor point for the text in local space
Vector2 textAnchorPivot = GetTextAnchorPivot(alignment);
Vector2 refPoint = Vector2.zero;
refPoint.x = Mathf.Lerp(inputRect.xMin, inputRect.xMax, textAnchorPivot.x);
refPoint.y = Mathf.Lerp(inputRect.yMin, inputRect.yMax, textAnchorPivot.y);
// Determine fraction of pixel to offset text mesh.
Vector2 roundingOffset = PixelAdjustPoint(refPoint) - refPoint;
// Apply the offset to the vertices
IList<UIVertex> verts = cachedTextGenerator.verts;
float unitsPerPixel = 1 / pixelsPerUnit;
//Last 4 verts are always a new line...
int vertCount = verts.Count - 4;
toFill.Clear();
UIVertex[] rVertex=new UIVertex[4];
if (roundingOffset != Vector2.zero)
{
for (int i = 0; i < vertCount; ++i)
{
int tempVertsIndex = i & 3;
rVertex[tempVertsIndex] = verts[i];
rVertex[tempVertsIndex].position *= unitsPerPixel;
rVertex[tempVertsIndex].position.x += roundingOffset.x;
rVertex[tempVertsIndex].position.y += roundingOffset.y;
if (tempVertsIndex == 3)
toFill.AddUIVertexQuad(rVertex);
}
}
else
{
for (int i = 0; i < verts.Count-4; i++)
{
int tempVertsIndex = i & 3;
rVertex[tempVertsIndex] = verts[i];
rVertex[tempVertsIndex].position.x += roundingOffset.x;
rVertex[tempVertsIndex].position.y += roundingOffset.y;
rVertex[tempVertsIndex].position *= unitsPerPixel;
rVertex[tempVertsIndex].uv1 = Vector2.zero;
if (m_OutLine && tempVertsIndex == 3)
{
ApplyShadowZeroAlloc(ref rVertex, m_OutLineColor, m_OutLineOffsetX, m_OutLineOffsetY, toFill);
ApplyShadowZeroAlloc(ref rVertex, m_OutLineColor, m_OutLineOffsetX, -m_OutLineOffsetY, toFill);
ApplyShadowZeroAlloc(ref rVertex, m_OutLineColor, -m_OutLineOffsetX, m_OutLineOffsetY, toFill);
ApplyShadowZeroAlloc(ref rVertex, m_OutLineColor, -m_OutLineOffsetX, -m_OutLineOffsetY, toFill);
toFill.AddUIVertexQuad(rVertex);
}
}
}
}
private void ApplyShadowZeroAlloc(ref UIVertex[] rVertex, Color rEffectColor, float rEffectDistanceX, float rEffectDistanceY, VertexHelper rHelper)
{
for (int i = 0; i < rVertex.Length; i++)
{
Vector3 rPosition = rVertex[i].position;
rPosition.x += rEffectDistanceX;
rPosition.y += rEffectDistanceY;
rVertex[i].position = rPosition;
rVertex[i].color = rEffectColor;
}
rHelper.AddUIVertexQuad(rVertex);
for (int i = 0; i < rVertex.Length; i++)
{
Vector3 rPosition = rVertex[i].position;
rPosition.x -= rEffectDistanceX;
rPosition.y -= rEffectDistanceY;
rVertex[i].color = color;
rVertex[i].position = rPosition;
}
}
}
Shader优化
OutlineEx.shader
Shader "TSF Shaders/UI/OutlineEx"
{
Properties
{
_MainTex("Main Texture", 2D) = "white" {}
_Color("Tint", Color) = (1, 1, 1, 1)
// 描边颜色和宽度
_OutlineColor("Outline Color", Color) = (1, 1, 1, 1)
_OutlineWidth("Outline Width", Int) = 1
_StencilComp("Stencil Comparison", Float) = 8
_Stencil("Stencil ID", Float) = 0
_StencilOp("Stencil Operation", Float) = 0
_StencilWriteMask("Stencil Write Mask", Float) = 255
_StencilReadMask("Stencil Read Mask", Float) = 255
_ColorMask("Color Mask", Float) = 15
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip("Use Alpha Clip", Float) = 0
}
SubShader
{
Tags
{
"Queue" = "Transparent"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
"PreviewType" = "Plane"
"CanUseSpriteAtlas" = "True"
}
Stencil
{
Ref[_Stencil]
Comp[_StencilComp]
Pass[_StencilOp]
ReadMask[_StencilReadMask]
WriteMask[_StencilWriteMask]
}
Cull Off
Lighting Off
ZWrite Off
ZTest[unity_GUIZTestMode]
Blend SrcAlpha OneMinusSrcAlpha
ColorMask[_ColorMask]
Pass
{
Name "OUTLINE"
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
sampler2D _MainTex;
fixed4 _Color;
fixed4 _TextureSampleAdd;
float4 _MainTex_TexelSize;
float4 _OutlineColor;
int _OutlineWidth;
struct appdata
{
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
float2 texcoord1 : TEXCOORD1;
float2 texcoord2 : TEXCOORD2;
fixed4 color : COLOR;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
float2 uvOriginXY : TEXCOORD1;
float2 uvOriginZW : TEXCOORD2;
fixed4 color : COLOR;
};
v2f vert(appdata IN)
{
v2f o;
o.vertex = UnityObjectToClipPos(IN.vertex);
o.texcoord = IN.texcoord;
o.uvOriginXY = IN.texcoord1;
o.uvOriginZW = IN.texcoord2;
o.color = IN.color * _Color;
return o;
}
// 检查点是否在给定矩形内
fixed IsInRect(float2 pPos, float4 pClipRect)
{
// step函数a>b返回0,否则返回1
pPos = step(pClipRect.xy, pPos) * step(pPos, pClipRect.zw);
return pPos.x * pPos.y;
}
// 根据圆的参数方程计算采样坐标,使用alpha值进行颜色混合
fixed SampleAlpha(int pIndex, v2f IN)
{
const fixed sinArray[12] = { 0, 0.5, 0.866, 1, 0.866, 0.5, 0, -0.5, -0.866, -1, -0.866, -0.5 };
const fixed cosArray[12] = { 1, 0.866, 0.5, 0, -0.5, -0.866, -1, -0.866, -0.5, 0, 0.5, 0.866 };
float2 pos = IN.texcoord + _MainTex_TexelSize.xy * float2(cosArray[pIndex], sinArray[pIndex]) * _OutlineWidth;
return IsInRect(pos, float4(IN.uvOriginXY, IN.uvOriginZW)) * (tex2D(_MainTex, pos) + _TextureSampleAdd).w * _OutlineColor.w;
}
fixed4 frag(v2f IN) : SV_Target
{
fixed4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
if (_OutlineWidth > 0)
{
color.w *= IsInRect(IN.texcoord, float4(IN.uvOriginXY, IN.uvOriginZW));
half4 val = half4(_OutlineColor.x, _OutlineColor.y, _OutlineColor.z, 0);
val.w += SampleAlpha(0, IN);
val.w += SampleAlpha(1, IN);
val.w += SampleAlpha(2, IN);
val.w += SampleAlpha(3, IN);
val.w += SampleAlpha(4, IN);
val.w += SampleAlpha(5, IN);
val.w += SampleAlpha(6, IN);
val.w += SampleAlpha(7, IN);
val.w += SampleAlpha(8, IN);
val.w += SampleAlpha(9, IN);
val.w += SampleAlpha(10, IN);
val.w += SampleAlpha(11, IN);
val.w = clamp(val.w, 0, 1);
color = (val * (1.0 - color.a)) + (color * color.a);
color.a = saturate(color.a);
color.a *= IN.color.a;
}
return color;
}
ENDCG
}
}
}
OutlineEx.cs
//————————————————————————————————————————————
// OutlineEx.cs
//
// Created by Chiyu Ren on 2018/9/12 23:03:51
//————————————————————————————————————————————
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
namespace TooSimpleFramework.UI
{
/// <summary>
/// UGUI描边
/// </summary>
public class Outline : BaseMeshEffect
{
public Color OutlineColor = Color.white;
[Range(0, 6)]
public int OutlineWidth = 0;
public Shader OutlineShader;
private static List<UIVertex> m_VetexList = new List<UIVertex>();
protected override void Start()
{
base.Start();
var shader = OutlineShader != null ? OutlineShader : Shader.Find("TSF Shaders/UI/OutlineEx");
base.graphic.material = new Material(shader);
// 修改additionalShaderChannels属性,将uv1和uv2传入shader
var v1 = base.graphic.canvas.additionalShaderChannels;
var v2 = AdditionalCanvasShaderChannels.TexCoord1;
if ((v1 & v2) != v2)
{
base.graphic.canvas.additionalShaderChannels |= v2;
}
v2 = AdditionalCanvasShaderChannels.TexCoord2;
if ((v1 & v2) != v2)
{
base.graphic.canvas.additionalShaderChannels |= v2;
}
this._Refresh();
}
#if UNITY_EDITOR
protected override void OnValidate()
{
base.OnValidate();
if (base.graphic.material != null)
{
this._Refresh();
}
}
#endif
private void _Refresh()
{
base.graphic.material.SetColor("_OutlineColor", this.OutlineColor);
base.graphic.material.SetInt("_OutlineWidth", this.OutlineWidth);
base.graphic.SetVerticesDirty();
}
public override void ModifyMesh(VertexHelper vh)
{
vh.GetUIVertexStream(m_VetexList);
this._ProcessVertices();
vh.Clear();
vh.AddUIVertexTriangleStream(m_VetexList);
}
// 处理顶点
private void _ProcessVertices()
{
for (int i = 0, count = m_VetexList.Count - 3; i <= count; i += 3)
{
var v1 = m_VetexList[i];
var v2 = m_VetexList[i + 1];
var v3 = m_VetexList[i + 2];
// 计算原顶点坐标中心点
var minX = _Min(v1.position.x, v2.position.x, v3.position.x);
var minY = _Min(v1.position.y, v2.position.y, v3.position.y);
var maxX = _Max(v1.position.x, v2.position.x, v3.position.x);
var maxY = _Max(v1.position.y, v2.position.y, v3.position.y);
var posCenter = new Vector2(minX + maxX, minY + maxY) * 0.5f;
// 计算原始顶点坐标和UV的方向
Vector2 triX, triY, uvX, uvY;
Vector2 pos1 = v1.position;
Vector2 pos2 = v2.position;
Vector2 pos3 = v3.position;
if (Mathf.Abs(Vector2.Dot((pos2 - pos1).normalized, Vector2.right))
> Mathf.Abs(Vector2.Dot((pos3 - pos2).normalized, Vector2.right)))
{
triX = pos2 - pos1;
triY = pos3 - pos2;
uvX = v2.uv0 - v1.uv0;
uvY = v3.uv0 - v2.uv0;
}
else
{
triX = pos3 - pos2;
triY = pos2 - pos1;
uvX = v3.uv0 - v2.uv0;
uvY = v2.uv0 - v1.uv0;
}
// 计算原始UV框
var uvMin = _Min(v1.uv0, v2.uv0, v3.uv0);
var uvMax = _Max(v1.uv0, v2.uv0, v3.uv0);
var uvOrigin = new Vector4(uvMin.x, uvMin.y, uvMax.x, uvMax.y);
// 为每个顶点设置新的Position和UV,并传入原始UV框
v1 = _SetNewPosAndUV(v1, this.OutlineWidth, posCenter, triX, triY, uvX, uvY, uvOrigin);
v2 = _SetNewPosAndUV(v2, this.OutlineWidth, posCenter, triX, triY, uvX, uvY, uvOrigin);
v3 = _SetNewPosAndUV(v3, this.OutlineWidth, posCenter, triX, triY, uvX, uvY, uvOrigin);
// 应用设置后的UIVertex
m_VetexList[i] = v1;
m_VetexList[i + 1] = v2;
m_VetexList[i + 2] = v3;
}
}
private static UIVertex _SetNewPosAndUV(UIVertex pVertex, int pOutLineWidth,
Vector2 pPosCenter,
Vector2 pTriangleX, Vector2 pTriangleY,
Vector2 pUVX, Vector2 pUVY,
Vector4 pUVOrigin)
{
// Position
var pos = pVertex.position;
var posXOffset = pos.x > pPosCenter.x ? pOutLineWidth : -pOutLineWidth;
var posYOffset = pos.y > pPosCenter.y ? pOutLineWidth : -pOutLineWidth;
pos.x += posXOffset;
pos.y += posYOffset;
pVertex.position = pos;
// UV
var uv = pVertex.uv0;
uv += pUVX / pTriangleX.magnitude * posXOffset * (Vector2.Dot(pTriangleX, Vector2.right) > 0 ? 1 : -1);
uv += pUVY / pTriangleY.magnitude * posYOffset * (Vector2.Dot(pTriangleY, Vector2.up) > 0 ? 1 : -1);
pVertex.uv0 = uv;
// 原始UV框
pVertex.uv1 = new Vector2(pUVOrigin.x, pUVOrigin.y);
pVertex.uv2 = new Vector2(pUVOrigin.z, pUVOrigin.w);
return pVertex;
}
private static float _Min(float pA, float pB, float pC)
{
return Mathf.Min(Mathf.Min(pA, pB), pC);
}
private static float _Max(float pA, float pB, float pC)
{
return Mathf.Max(Mathf.Max(pA, pB), pC);
}
private static Vector2 _Min(Vector2 pA, Vector2 pB, Vector2 pC)
{
return new Vector2(_Min(pA.x, pB.x, pC.x), _Min(pA.y, pB.y, pC.y));
}
private static Vector2 _Max(Vector2 pA, Vector2 pB, Vector2 pC)
{
return new Vector2(_Max(pA.x, pB.x, pC.x), _Max(pA.y, pB.y, pC.y));
}
}
}
文字渐变
Gradient.cs 由上到下渐变
// 渐变效果
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
[AddComponentMenu("UI/Effects/Gradient", 13)]
public class Gradient : BaseMeshEffect
{
[SerializeField] private Color32 m_TopColor = Color.white;
[SerializeField] private Color32 m_BottomColor = Color.black;
public Color32 topColor
{
get { return m_TopColor; }
set { m_TopColor = value; }
}
public Color32 bottomColor
{
get { return m_BottomColor; }
set { m_BottomColor = value; }
}
public override void ModifyMesh(VertexHelper vh)
{
if (!this.IsActive())
return;
List<UIVertex> vertexList = new List<UIVertex>();
vh.GetUIVertexStream(vertexList);
ModifyVertices(vertexList);
vh.Clear();
vh.AddUIVertexTriangleStream(vertexList);
}
public void ModifyVertices(List<UIVertex> vertexList)
{
if (!IsActive() || vertexList.Count <= 0)
{
return;
}
for (int i = 0; i < vertexList.Count;)
{
float bottomY = vertexList[i].position.y;
float topY = bottomY;
float dis = 1f;
for (int k = 1; k < 6; k++)
{
float y = vertexList[k + i].position.y;
if (y > topY)
{
topY = y;
}
else if (y < bottomY)
{
bottomY = y;
}
}
dis = topY - bottomY;
for (int k = 0; k < 6; k++)
{
UIVertex vertText = vertexList[k + i];
vertText.color = Color32.Lerp(m_BottomColor, m_TopColor, (vertText.position.y - bottomY) / dis);
vertexList[k + i] = vertText;
}
i += 6;
}
}
}
TextGradient.cs 支持横向,纵向,左上至右下,左下至右上渐变
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(Text))]
public class TextGradient : BaseMeshEffect
{
public enum GradientDirection { Horizontal, Vertical,LeftUpToRightDown,LeftDownToRightUp }
[SerializeField] //定义序列化属性,一会的Editor中需要通过定义的这个属性找到该字段
public Color32 topColor = Color.white;//顶部颜色
[SerializeField]
public Color32 bottomColor = Color.black;//底部颜色
[SerializeField]
public GradientDirection gradientDirection;//渐变方向
[SerializeField]
public bool useEffect = false;//是否使用阴影
[SerializeField]
public Color effectColor = new Color(0f, 0f, 0f, 0.5f);//阴影颜色
[SerializeField]
public Vector2 effectDistance = new Vector2(1f, -1f);//阴影偏移
private const int DefautlVertexNumPerFont = 6;//顶点数
List<UIVertex> vertexBuffers = new List<UIVertex>();
public Mesh mesh = null;
/// <summary>
/// 给顶点着色
/// </summary>
/// <param name="vertexList"></param>
/// <param name="index"></param>
/// <param name="color"></param>
private void ModifyVertexColor(List<UIVertex> vertexList, int index, Color color)
{
UIVertex temp = vertexList[index];
temp.color = color;
vertexList[index] = temp;
}
//修改网格时调用
public override void ModifyMesh(VertexHelper vh)
{
if (!IsActive())
{
return;
}
vh.GetUIVertexStream(vertexBuffers);//获取顶点
Debug.Log(vertexBuffers.Count);
//在Inspector中显示网格
if (mesh == null)
{
mesh = new Mesh();
}
vh.FillMesh(mesh);
int count = vertexBuffers.Count;
if (count > 0)
{
/**给顶点着色( 这里需要明白顶点的顺序 )
* 5-0 ---- 1
* | \ |
* | \ |
* | \ |
* | \ |
* 4-----3-2
**/
for (int i = 0; i < count; i += DefautlVertexNumPerFont)
{
//分别设置每个顶点的颜色
switch (gradientDirection)
{
case GradientDirection.Horizontal:
ModifyVertexColor(vertexBuffers, i, topColor);
ModifyVertexColor(vertexBuffers, i + 1, topColor);
ModifyVertexColor(vertexBuffers, i + 2, bottomColor);
ModifyVertexColor(vertexBuffers, i + 3, bottomColor);
ModifyVertexColor(vertexBuffers, i + 4, bottomColor);
ModifyVertexColor(vertexBuffers, i + 5, topColor);
break;
case GradientDirection.Vertical:
ModifyVertexColor(vertexBuffers, i, topColor);
ModifyVertexColor(vertexBuffers, i + 1, bottomColor);
ModifyVertexColor(vertexBuffers, i + 2, bottomColor);
ModifyVertexColor(vertexBuffers, i + 3, bottomColor);
ModifyVertexColor(vertexBuffers, i + 4, topColor);
ModifyVertexColor(vertexBuffers, i + 5, topColor);
break;
case GradientDirection.LeftUpToRightDown:
ModifyVertexColor(vertexBuffers, i, topColor);
ModifyVertexColor(vertexBuffers, i + 1, bottomColor);
ModifyVertexColor(vertexBuffers, i + 2, topColor);
ModifyVertexColor(vertexBuffers, i + 3, topColor);
ModifyVertexColor(vertexBuffers, i + 4, bottomColor);
ModifyVertexColor(vertexBuffers, i + 5, topColor);
break;
case GradientDirection.LeftDownToRightUp:
ModifyVertexColor(vertexBuffers, i, bottomColor);
ModifyVertexColor(vertexBuffers, i + 1, topColor);
ModifyVertexColor(vertexBuffers, i + 2, bottomColor);
ModifyVertexColor(vertexBuffers, i + 3, bottomColor);
ModifyVertexColor(vertexBuffers, i + 4, topColor);
ModifyVertexColor(vertexBuffers, i + 5, bottomColor);
break;
default:
break;
}
}
}
if (useEffect)//是否使用阴影(如果不需要阴影功能可以这部分代码删掉)
{
//扩充一倍的顶点容量
var neededCapacity = vertexBuffers.Count * 2;
if (vertexBuffers.Capacity < neededCapacity)
vertexBuffers.Capacity = neededCapacity;
for (int i = 0, cnt = vertexBuffers.Count; i < cnt; ++i)
{
var vt = vertexBuffers[i];
vertexBuffers.Add(vt);
Vector3 v = vt.position;
v.x += effectDistance.x;
v.y += effectDistance.y;
vt.position = v;
vt.color = effectColor;
vertexBuffers[i] = vt;
}
}
vh.Clear();
//这个方法向VertexHelper中批量增加三角形顶点数据,参数的长度必须是三的倍数
vh.AddUIVertexTriangleStream(vertexBuffers);
}
/// <summary>
/// 在Scene中显示顶点
/// </summary>
void OnDrawGizmos()
{
Gizmos.color = Color.red;//设置颜色
for (int i = 0; i < vertexBuffers.Count; i++)
{
//把mesh顶点转为世界坐标
Vector3 targetPosition = transform.TransformPoint(vertexBuffers[i].position);
Gizmos.DrawSphere(targetPosition, 5f);
}
}
}
参考资料
|