SetMaterialDirty是Graphic的方法，可以参考UGUI内核大探究（七）Graphic

Cull方法：

public virtual void Cull(Rect clipRect, bool validRect)
{
if (!canvasRenderer.hasMoved)
return;

var cull = !validRect || !clipRect.Overlaps(canvasRect);
var cullingChanged = canvasRenderer.cull != cull;
canvasRenderer.cull = cull;

if (cullingChanged)
{
m_OnCullStateChanged.Invoke(cull);
SetVerticesDirty();
}
}

SetClipRect方法很简单，只是根据输入validRectcanvasRenderer开启或关闭矩形裁剪（开启时传递参数clipRect）。

public virtual Material GetModifiedMaterial(Material baseMaterial)
{
var toUse = baseMaterial;

if (m_ShouldRecalculateStencil)
{
m_ShouldRecalculateStencil = false;
}

// if we have a Mask component then it will
// generate the mask material. This is an optimisation
// it adds some coupling between components though :(
if (m_StencilValue > 0 && GetComponent<Mask>() == null)
{
var maskMat = StencilMaterial.Add(toUse, (1 << m_StencilValue) - 1, StencilOp.Keep, CompareFunction.Equal, ColorWriteMask.All, (1 << m_StencilValue) - 1, 0);
}
}

public static int GetStencilDepth(Transform transform, Transform stopAfter)
{
var depth = 0;
if (transform == stopAfter)
return depth;

var t = transform.parent;
var components = ListPool<Component>.Get();
while (t != null)
{
for (var i = 0; i < components.Count; ++i)
{
{
++depth;
break;
}
}

if (t == stopAfter)
break;

t = t.parent;
}
ListPool<Component>.Release(components);
return depth;
}

public virtual void PerformClipping()
{
// if the parents are changed
// or something similar we
// do a recalculate here
if (m_ShouldRecalculateClipRects)
{
m_ShouldRecalculateClipRects = false;
}

// get the compound rects from
// the clippers that are valid
bool validRect = true;
Rect clipRect = Clipping.FindCullAndClipWorldRect(m_Clippers, out validRect);
if (clipRect != m_LastClipRectCanvasSpace)
{
for (int i = 0; i < m_ClipTargets.Count; ++i)
m_ClipTargets[i].SetClipRect(clipRect, validRect);

m_LastClipRectCanvasSpace = clipRect;
m_LastClipRectValid = validRect;
}

for (int i = 0; i < m_ClipTargets.Count; ++i)
m_ClipTargets[i].Cull(m_LastClipRectCanvasSpace, m_LastClipRectValid);
}

Clipping的FindCullAndClipWorldRect方法将这些m_Clippers的canvasRect（最近的Canvas父对象的矩形区域）求交集，得到一个最小的裁剪区域（如果这个裁剪区域不合理，validRect便为false）。接着，如果新的出来的clipRect与旧的不同，那么遍历m_ClipTargets，为他们设置裁剪区域，就是我们前面讲的SetClipRect。最后调用所有IClippable的剔除方法（前面讲的Cull）。

public virtual Material GetModifiedMaterial(Material baseMaterial)
{
if (graphic == null)
return baseMaterial;

if (stencilDepth >= 8)
{
Debug.LogError("Attempting to use a stencil mask with depth > 8", gameObject);
return baseMaterial;
}

int desiredStencilBit = 1 << stencilDepth;

// if we are at the first level...
// we want to destroy what is there
if (desiredStencilBit == 1)
{

graphic.canvasRenderer.popMaterialCount = 1;

}

//otherwise we need to be a bit smarter and set some read / write masks
var maskMaterial2 = StencilMaterial.Add(baseMaterial, desiredStencilBit | (desiredStencilBit - 1), StencilOp.Replace, CompareFunction.Equal, m_ShowMaskGraphic ? ColorWriteMask.All : 0, desiredStencilBit - 1, desiredStencilBit | (desiredStencilBit - 1));

graphic.canvasRenderer.hasPopInstruction = true;
var unmaskMaterial2 = StencilMaterial.Add(baseMaterial, desiredStencilBit - 1, StencilOp.Replace, CompareFunction.Equal, 0, desiredStencilBit - 1, desiredStencilBit | (desiredStencilBit - 1));
graphic.canvasRenderer.popMaterialCount = 1;

}

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120