UGUI源码(三)Image
Image.cs
//部分源码
public class Image : MaskableGraphic, ISerializationCallbackReceiver, ILayoutElement, ICanvasRaycastFilter
{
//更新网格(核心函数)
protected override void OnPopulateMesh(VertexHelper toFill)
{
if (activeSprite == null)
{
base.OnPopulateMesh(toFill);
return;
}
//Image的4种显示模式(简单,九宫,平铺,填充)
//Type.Simple: 简单的通过顶点颜色UV生成Mesh,顶点与三角面数量保持不变
//Type.Sliced: 当Sprite被编辑(Sprite Editor),使其边界值(activeSprite.border)>0时可以使用该类型。根据Sprite编辑后的信息,至多可划分9块矩形区域,处在边界区域内的图像会被拉伸,边界区域外的图像保持不变。
//Type.Tiled : 计算边界区域内的图像大小,按照此大小平铺满整个矩形。矩形区域数量取决于平铺数量。
//Type.Filled: 主要通过fillAmount(填充率)来对矩形进行不同类型的填充(水平、垂直、角度)常见的进度条、技能冷却cd效果等应用
switch (type)
{
case Type.Simple:
GenerateSimpleSprite(toFill, m_PreserveAspect);
break;
case Type.Sliced:
GenerateSlicedSprite(toFill);
break;
case Type.Tiled:
GenerateTiledSprite(toFill);
break;
case Type.Filled:
GenerateFilledSprite(toFill, m_PreserveAspect);
break;
}
}
//简单采样模式
void GenerateSimpleSprite(VertexHelper vh, bool lPreserveAspect)
{
Vector4 v = GetDrawingDimensions(lPreserveAspect);
//获取sprite中存储的UV信息
var uv = (activeSprite != null) ? Sprites.DataUtility.GetOuterUV(activeSprite) : Vector4.zero;
//存储顶点、颜色、uv数据
var color32 = color;
vh.Clear();
vh.AddVert(new Vector3(v.x, v.y), color32, new Vector2(uv.x, uv.y));
vh.AddVert(new Vector3(v.x, v.w), color32, new Vector2(uv.x, uv.w));
vh.AddVert(new Vector3(v.z, v.w), color32, new Vector2(uv.z, uv.w));
vh.AddVert(new Vector3(v.z, v.y), color32, new Vector2(uv.z, uv.y));
//存储三角面的顶点序列
vh.AddTriangle(0, 1, 2);
vh.AddTriangle(2, 3, 0);
}
}
Image使用图集实现动态合批,减少DrawCall原理
image在绘制网格(OnPopulateMesh)的时候,就是通过(Sprites.DataUtility.GetOuterUV(activeSprite))把得到的UV采样值填充到顶点的UV中,
所以不同的ui使用相同的材质、shader、贴图,只是拥有了不同的uv信息,符合动态合批的规则,减少DrawCall