系列
Graphic
Related Class: Graphic、MaskableGraphic、GraphicRegistry、CanvasUpdateRegistry、VertexHelper
Related Interface: ICanvasElement、IMeshModifier、IClippable、IMaskable、IMaterialModifier
Intro: 图形组件的基类,基础中的基础组件
- ICanvasElement: Canvas元素(重建接口),当Canvas发生更新时重建(void Rebuild)
- IMeshModifier:网格处理接口
- IClippable:裁剪相关处理接口
- IMaskable:遮罩处理接口
- IMaterialModifier:材质处理接口
Graphic 作为图像组件的基类,主要实现了网格与图像的生成/刷新方法。
在生命周期Enable阶段、Editor模式下的OnValidate中、层级/颜色/材质改变时都会进行相应的刷新(重建)。
重建过程主要通过 CanvasUpdateSystem 最终被Canvas所重新渲染。
详情请见:CanvasUpdateSystem源码剖析
重建主要分为两个部分:顶点重建(UpdateGeometry)与 材质重建(UpdateMaterial)
更新完成的结果会设置进CanvasRenderer,从而被渲染形成图像。
本章着重分析Graphic源码部分,接下来的章节会重点分析Graphic继承链下的MaskableGraphic与衍生出来的组件们。
GraphicRegistry
管理同Canvas下的所有Graphic对象
Dictionary<Canvas, IndexedSet<Graphic>> m_Graphics
Graphic 初始化时(Enable)会寻找其最近根节点的Canvas组件,并以此为key存储在GraphicRegistry中。
Rebuild
public virtual void Rebuild(CanvasUpdate update)
{
if (canvasRenderer.cull)
return;
switch (update)
{
case CanvasUpdate.PreRender:
if (m_VertsDirty)
{
UpdateGeometry();//网格更新
m_VertsDirty = false;
}
if (m_MaterialDirty)
{
UpdateMaterial();//材质纹理更新
m_MaterialDirty = false;
}
break;
}
}
UpdateGeometry
Graphic 顶点(网格)更新与生成,发生顶点重建时会被调用。
过程:
- 更新VertexHelper数据
- 遍历身上的IMeshModifier组件(MeshEffect组件,实现网格的一些特效,例如Shadow、Outline),更新VertexHelper数据
- 将最终的顶点数据设置给 workerMesh,并将workerMesh设置进canvasRenderer中,进行渲染。
private void DoMeshGeneration()
{
if (rectTransform != null && rectTransform.rect.width >= 0 && rectTransform.rect.height >= 0)
OnPopulateMesh(s_VertexHelper);//更新顶点信息
else
s_VertexHelper.Clear(); // clear the vertex helper so invalid graphics dont draw.
var components = ListPool<Component>.Get();
GetComponents(typeof(IMeshModifier), components);
for (var i = 0; i < components.Count; i++)
((IMeshModifier)components[i]).ModifyMesh(s_VertexHelper);//若由网格特效,则由特效继续更新顶点信息
ListPool<Component>.Release(components);
s_VertexHelper.FillMesh(workerMesh);
canvasRenderer.SetMesh(workerMesh);//设置当canvasRenderer中
}
基础的网格由 4 个顶点 2 个三角面构成
VertexHelper : 临时存储有关顶点的所有信息,辅助生成网格
- List<Vector3> m_Positions : 顶点位置
- List<Color32> m_Colors :顶点颜色
- List<Vector2> m_Uv0S :第1个顶点UV坐标
- List<Vector2> m_Uv1 :第2个顶点UV坐标
- List<Vector2> m_Uv2S :第3个顶点UV坐标
- List<Vector2> m_Uv3S :第4个顶点UV坐标
- List<Vector3> m_Normals :法线向量
- List<Vector4> m_Tangents : 切线向量
- List<int> m_Indices : 三角面顶点索引
BaseMeshEffect
- PositionAsUV1: 根据顶点坐标设置UV1坐标(一般为法线贴图,不加此组件时UV1坐标默认是Vector2.zero)
- Shadow:在顶点数基础上增加了一倍的顶点数,并根据偏移(effectDistance)设置新顶点的坐标,实现阴影效果。
- Outline:继承自Shadow,原理就是分别在四个角(根据effectDistance换算)上实现了四个Shadow,即增加了4倍的顶点数。
UpdateMaterial
Graphic 材质更新,发生材质重建时会被调用。
过程:
- 获取自身材质material,遍历身上的IMaterialModifier组件(材质处理组件,实现材质特效,例如Mask),更新 materialForRendering
- 将最终的材质数据materialForRendering与纹理mainTexture设置进canvasRenderer中,进行渲染。
protected virtual void UpdateMaterial()
{
if (!IsActive())
return;
canvasRenderer.materialCount = 1;
canvasRenderer.SetMaterial(materialForRendering, 0);
canvasRenderer.SetTexture(mainTexture);
}
public virtual Material materialForRendering
{
get
{
var components = ListPool<Component>.Get();
GetComponents(typeof(IMaterialModifier), components);
var currentMat = material;
for (var i = 0; i < components.Count; i++)
currentMat = (components[i] as IMaterialModifier).GetModifiedMaterial(currentMat);//这里由IMaterialModifier组件对currentMat进行特效化处理,得到最终展示的材质
ListPool<Component>.Release(components);
return currentMat;
}
}
.
.
.
.
.
嗨,我是作者Vin129,逐儿时之梦正在游戏制作的技术海洋中漂泊。知道的越多,不知道的也越多。希望我的文章对你有所帮助:)