系列
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,逐兒時之夢正在遊戲製作的技術海洋中漂泊。知道的越多,不知道的也越多。希望我的文章對你有所幫助:)