您的位置:首页 > 其它

XNA下的中文显示

2009-05-17 23:04 197 查看

[align=center]XNA下的中文显示 [/align]
仅供个人学习使用,请勿转载,勿用于任何商业用途。


为了平台兼容性,XNA并没有类似D3DFont的函数。XNA2.0增加了对bitmap font的支持,把需要显示的字体预处理到纹理上,作为sprite来显示。对印欧语系来说,文字只由少量字母组成, SpriteFont完全能满足需要。但对于中文,日语这样有上万字符的文字来说,显然就无法处理了,因为生成这些字符可能需要几十m的纹理。当然,如果你只需要1,2千字符显示固定的任务和菜单信息,SpriteFont还是可以胜任的。但如果程序允许用户输入,比如一个聊天系统,那么所显示的字符是无法预知,我们需要一些其他方法来显示字体。

通常为了增加功能,就需要牺牲通用性,这里的解决方案只能用于pc上的windows系统,我们将使用GDI+来辅助渲染字体。方法很简单,仍然基于bitmap font原理,只不过我们把需要的字符在程序运行时动态渲染到纹理上,最后的目标是得到一个类似:DrawString(text, font, x, y, color) 的方法。

最简单的方法是对于每一个需要绘制的字符串,我们先用GDI+把它绘制到一张透明纹理上,然后在把这张纹理渲染到XNA界面。可惜这个方法完全没有可操作性,与XNA相比,GDI+是非常非常缓慢的,以至少30fps来绘图几乎是不可能的,会极大降低程序性能。那应该怎么办呢?可以考虑把需要显示的字符”缓存”到一张纹理上,缓存之后,再绘制这个字符就不需要调用GDI+,也不需要纹理拷贝,以此提高渲染速度。

public void DrawString(string text, XNAFont font, int x, int y, XnaColor color)

{

……create character cache

……charFamily = charFamilies[font];

spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None);

Rectangle rect;

for (int i = 0; i < text.Length; i++)

{

rect = charFamily[text[i]];

spriteBatch.Draw(fontTexture.xnaTexture, new Vector2(x, y), rect, color);

x += rect.Width;

}

spriteBatch.End();

}

我们甚至可以让DrawString接收char[]或者StringBuilder类型的文本进行绘制。此外,再添加一个DrawStringInRegion()也很容易,只需要在添加额外的一两个参数而已。由于字符已经变成了sprite,我们还可以指定任意的颜色,特效和所有对sprite有效的变换。

性能测试:

在Q6600,8800GT,4G内存的XP上,使用同一字体在随机位置绘制一个包含30个字符的字符串。迭代200次FPS在245帧左右,100次FPS在450帧左右,50次则增加到了700帧以上。即使对5w字的随机文本进行渲染,也几乎不需要重建纹理缓冲。

ps:

这几天加强了字体系统, 功能和性能都已经比较完善了:

1.支持任意字体和大小.

2. 支持string和StringBuilder

3. 支持从字符串中的某个指定位置开始绘制.

4. 支持x,y方向上的非均匀缩放

5. 支持2D空间内的旋转.

6. 支持任意颜色

7. 添加了DrawStringInRegion(), 在指定区域内显示文字,支持自动换行, 裁剪超出显示区域的文字. 暂时还不支持缩放和旋转.

8. 低内存占用,大约5mb左右

最终的接口只包含2个类,Font和FontSystem。非常容易集成到其他系统:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: