NGUI直接在UILabel组件中接入了Shadow、Gradient和outline选项,但在UGUI中是通过另外的组件单独提供,比如outline、shader等。这篇文章主要记录这几个文字效果实现的思路和流程。
1. 实现思路
1. UGUI源码分析
UGUI 的 Text 渲染的过程是由 TextGenerator 产生顶点数据,配合字体产生的贴图最终显示在屏幕上 . 下图为Text组件的继承树。
UGUI中很多渲染相关的组件都是继承自Graphics,而Graphics还在Canvas绘制之前进行重建。Graphics中定义了渲染框架,核心代码如下。Text、Image组件的需要自己实现 protected virtual void OnPopulateMesh(VertexHelper vh) 方法来填充需要的数据。Unity提供了IMeshModifier接口供外部使用,如果在Text组件所在物体中存在IMeshModifier类型的组件,则会调用ModifyMesh方法允许你获得渲染数据。也就是说可以通过这种方式进行mesh、贴图等数据的修改。
protected virtual void UpdateGeometry(){if (useLegacyMeshGeneration)DoLegacyMeshGeneration();elseDoMeshGeneration();}private void DoMeshGeneration(){if (rectTransform != null && rectTransform.rect.width >= 0 && rectTransform.rect.height >= 0)//获取数据OnPopulateMesh(s_VertexHelper);elses_VertexHelper.Clear(); // clear the vertex helper so invalid graphics dont draw.var components = ListPool
2. 实现接口
Unity提供了BaseMeshEffect类型,继承自IMeshModifier,提供 public abstract void ModifyMesh(VertexHelper vh); 接口。不过从4.7到现在这个接口修改了很多次,5.3版本是这个,5.5版本似乎又做了修改。文字的各种特效就可以通过这个接口获得渲染数据并进行修改即可。
2. 颜色渐变(Gradient)
渐变其实就是根据需要进行渐变的方向和颜色修改顶点的颜色值。 如果只考虑上下方向的渐变,可以计算字符上下最大和最小值,然后进行插值即可计算出需要的颜色。对于多方向的渐变实现稍稍麻烦点,原理类似。核心代码如下:
UGUI 中默认带有Shadow的组件,也是对ModifyMesh进行重载。然后将网格数据复制一份并向指定方向移动指定像素,然后填充到顶点数据中。也就是说,Shadow实现是通过增加顶点数据实现的。 outline的实现传统的做法是在4个方向或者8个方向进行Shodow操作。换句话说顶点数需要增加8倍,大量使用请谨慎。 4方向Outlin美术经常不满足的其效果,所以有时候会需要8方向描边的outline8, 甚至更多。基于shadow方式的outline实现可以参考开源代码:https://github.com/n-yoda/unity-vertex-effects 。换汤不换药吧,越好的效果顶点增加的越多。 基于Shadow的实现方式内存占用比较高,当然还有别的思路,可以参考网页中描述的方式。其详细流程: outline的几种实现方式根据具体需求使用,云风在博客中也给出一种优化策略可参考。 public override void ModifyMesh(VertexHelper vh){var vertexList = new List
3. 阴影(Shadow)
// X y 为 shadow大小
protected void ApplyShadowZeroAlloc(List
{UIVertex vt;var neededCapacity = verts.Count + end - start;if (verts.Capacity 4. 勾边 (Outline)
1. 基于Shadow
public override void ModifyMesh(VertexHelper vh){var verts = ListPool
2 . 效果扩展
几种效果的图示,中文字边缘比较明显。Circle的边缘更圆滑一些,Shadow操作的次数和8方向相同。3. 基于Mesh实现
5.结论
总之,UGUI对字体效果的支持不算很好,像图文混排等等都需要自己做扩展,据说收购了TexmeshPro对自身text系统进行扩展,期待。