我在项目中遇到一个需求,需要在Camera上使用GL绘制文字。最好的办法是使用BMFont文字,将文字以纹理的形式绘制在Camera上。
会用到的工具:NGUI,BMFont。这两个工具在网上很容易找到。
1.首先使用BMFont导出文字图集,我这里只需要导出数字,所以我只选中了数字,如下图
2.打开Options->Export options,将Bit depth选择为32,将Font descriptor选择为Text。点击OK。
3.点击Options->Save bitmap as…,将bitmap保存到指定路径下。我这里命名为f,所以保存在本地是
使用文本打开f.fnt文件。看见是这样的
可以看见这里保存的是每个字符的信息,包括它的id,宽高,坐标等。
需要注意的是:图片的坐标系的原点在坐上角。我们看文件中id等于56的坐标是(0,0),id ==56 是数字8,它的左上角坐标在原点。我们看f_0.png中,8确实是在最上角。
1.使用NGUI创建BMFont字体,如图
2.OK,接下来开始愉快的Coding。
这里使用NGUI的主要目的是因为它自带了解析字体文本文件的功能。
BMFont.GetGlyph()方法返回BMGlyph类,该类里就是每个字符的信息,我们使用这些信息来计算字符的UV。
由于BMFont的坐标系的Y轴和Unity的Y轴是相反的,所以我们需要用一个矩阵将其转变成Unity的坐标系当做
Matrix4x4 uvMatrix = Matrix4x4.identity;
uvMatrix.m11 = -1;//(表示Y轴取反)
uvMatrix.m13 = 1;//(表示在Y轴方向平移1个单位,由于反转坐标是在原点反转,说以原来是Y是1的转后就变成-1,所以还需要一次平移将-1变成0)
接下来计算UV。
private Vector3[] getUVbyChar(int index)
{
int texWidth = m_font.bmFont.texWidth;
int texHeight = m_font.bmFont.texHeight;
BMGlyph bgph = m_font.bmFont.GetGlyph(index, false);
float x = (float)bgph.x / (float)texWidth;
float y = (float)bgph.y / (float)texHeight;
float width = (float)bgph.width / (float)texWidth;
float height = (float)bgph.height / (float)texHeight;
Vector3[] uvs = new Vector3[4];
uvs[0] = uvMatrix * new Vector3(x, height + y, 0);
uvs[1] = uvMatrix * new Vector3(x, y, 0);
uvs[2] = uvMatrix * new Vector3(x + width, y, 0);
uvs[3] = uvMatrix * new Vector3(x + width, height + y, 0);
return uvs;
}
这里返回的是每个字符的UV数组。然后使用GL.Begin(GL.QUADS)绘制。每个文字就是一个四边形。
Vector3[] vertexs = { new Vector3(0.5f, 0, 0), new Vector3(0.5f, 1, 0), new Vector3(1, 1, 0), new Vector3(1, 0, 0) };
private void DrawWords(Vector3[] vertexs,Vector3[] uvs)
{
for (int i = 0; i < 4; i++)
{
GL.TexCoord(uvs[i]);
GL.Vertex(vertexs[i]);
}
}
OK,到现在我们就绘制完成了!