Unity里面如何实现圆形图片呢?
1.可以使用 Mask 来实现。
但是会有额外的 DrawCall ,使用 Mask 明显会增加 4 个 DrawCall 。
Mask 本身占 2 个,上下两层各占一个(如果能合批的话)。
Mask实现原理:
通过 GPU 的 Shader 实现,第一个 DrawCall 是一个在底层模板绘制一个区域的指令,根据 Image 传进来图片的a值,确定裁剪区域。之后 Mask 节点下面的元素会根据这个区域计算Alpha的值,最后一个 Mask 是绘制区域结束的指令。
2.自定义 MaskGraphic 组件。
Image组件默认以矩形形式渲染。
只需重写圆形形状的渲染顶点、三角面片信息,根本不需要Mask就能渲染出圆形Image。
通过重写 OnPopulateMesh
方法,来自定义顶点信息。
代码如下:
public class CircleImage : Image
{
//分割的片段数
public int segements = 20;
/// <summary>
/// UI元素生成顶点数据时调用
/// </summary>
protected override void OnPopulateMesh(VertexHelper vh)
{
vh.Clear();
//圆点
var pivot = this.rectTransform.pivot;
var rect = this.rectTransform.rect;
Vector2 center = new Vector2((rect.width * (0.5f - pivot.x)), (rect.height * (0.5f - pivot.y)));
vh.AddVert(CreateUIVertex(center, new Vector2(0.5f, 0.5f), this.color));
float radius = rect.width / 2f;
//每段的弧度
float radians = Mathf.PI * 2 / this.segements;
int count = this.segements;
//每一个圆弧上的顶点
for (int i = 0; i < count; i++)
{
float angdeg = radians * i;
float x = center.x + radius * Mathf.Cos(angdeg);
float y = center.y + radius * Mathf.Sin(angdeg);
float uvX = (radius * Mathf.Cos(angdeg) + radius) / (2 * radius);
float uvY = (radius * Mathf.Sin(angdeg) + radius) / (2 * radius);
vh.AddVert(CreateUIVertex(new Vector3(x, y), new Vector2(uvX, uvY), color: this.color));
}
for (int i = 0; i < count; i++)
{
int id0 = 0;
int id1 = i + 2;
if (id1 > count)
{
id1 %= count;
}
int id2 = i + 1;
vh.AddTriangle(id0, id1, id2);
}
}
public UIVertex CreateUIVertex(Vector3 position, Vector2 uv0, Color color)
{
UIVertex uiVertex = new UIVertex()
{
position = position,
uv0 = uv0,
color = color
};
return uiVertex;
}
}
注意要点:
1.对中心点要进行参与计算。
2.UV的坐标是0-1的。
3.三角面的顺序是顺时针的。
小技巧:
1.也可以实现类似技能的CD效果,只需添加一个角度,大于此角度显示正常颜色,小于此角度显示黑色。
2.边缘锯齿可通过外层覆盖解决。
3.边缘锯齿也可以通过透明度来解决。