LOG.ZS.0001.基于Freetype的游戏字体渲染优化思路
Total |
Utf8-ucs2 |
Html_parse |
Layout |
Render_string |
Init_texture |
Ft_load_glyph |
|
原始 |
2293 |
1 |
26 |
708 |
1556 |
2 |
1403 |
上表用于记录优化各步骤的消耗时间。
生成的文本纹理,文本是加州宾馆的全歌词。
原始版本整个纹理的生成耗时2300毫秒左右,可以看到实际是慢得发指。
究其原因,是由于实现iron引擎的时候未进行任何性能方面的考虑。
上述时间表的构成:
total : 总消耗时间
utf8-ucs2: 将utf8字符串转换为ucs2的时间
html_parse : 引擎需要支持一定程度的富文本,所以需要支持简单的html解析.
render_string: 将字符串转换为纹理所消耗的总时间
Ft_load_glygh : 在整个过程中, 调用Ft_load_glygh 消耗的总时间。
由以上分析可知,最消耗时间的调用是Ft_load_glygh。
尚不知道为什么Ft_load_glygh消耗的时间这么大,原以为是因为每次Ft_load_glygh会到文件中去查询加载具体字符数据,而将程序改造成从内存加载字库数据,仍然耗时巨大。
如果freetype本身无法优化,那么就需要从其他方向来考虑这个问题。
首先重新阐述一下字体渲染的需求:
(1) 常规的字体属性需要支持,如font_size
(2) 能够为字体指定边框颜色,边框尺寸,填充颜色。
(3) 能够按单行,或者多行进行布局。
(4) 能够一定程度支持富文本, 例如为精灵设置text = <font style="color:#FF0000; ">某X</font>施展了<font style=" color:#FF0000;outline:1;outline_color:#00FFFF">愤怒一击</font>
(5) 性能不需要达到多高,但至少做到切换场景,不能因为字体纹理生成而产生明显卡顿(特别是有动态字体的时候,比如聊天).
综上所属,一次纹理生成的过程至少包含如下逻辑
--> 将utf8转换为ucs2
--> 解析富文本
--> 计算布局
--> 生成纹理
这里需要说明的是: 按上表所述, Layout 消耗掉708ms的原因是,Layout需要获取各字符的尺寸. 所以调用了FT_Load_Glyph, 该函数起码就占用了700ms。
之后在生成纹理过程中,对FT_Load_Glyph再次进行调用,所以不慢都不行。
问题大致清楚后,考虑解决方案.
目前初步考虑的优化方案是:避免每次生成字符纹理,都去调用Ft_load_glyph加载字模数据,改为采用缓存机制.仅在第一次加载字体时,才会调用Ft_load_glyph。之后的调用,会从缓存中读取。 至于是不是要对缓存设置阀值,控制内存增长,这里先暂时不考虑。
那么接下来就需要确定我到底应该缓存什么。
缓存什么呢,缓存什么呢。
先把参考用的freetype库,生成带边框字体的example代码贴上。
http://www.freetype.org/freetype2/docs/tutorial/example2.cpp
这个范例代码写得丑陋,但是逻辑还是很简单的。
大体上的过程实际就是加载字模后,
获取字模fill 部分的Span表,
获取字模outline 部分的Span表,
将两部分数据打到一个Bitmap中.
这个Span结构需要特别说明一下,很有意思。
struct Span { Span() { } Span(int _x, int _y, int _width, int _coverage) : x(_x), y(_y), width(_width), coverage(_coverage) { } int x, y, width, coverage; };
他实际描述的是一条横向扫描线,起点在(x, y), 宽度为with, converage 存储的是灰度数据(0-255)。你后面需要做的是拿到这个表以后,进行遍历,将Span数据外加外部输入的颜色值(边框颜色 和 填充颜色) 转换成最终的Bitmap。
由于我们的字体支持包边,所以我们可能会拿到两个Span表,一个是用于渲染outline的,姑且叫他outlineSpans, 另一个是用于渲染填充区的,姑且叫他fillSpans。
实际上,outlineSpan 和 fillSpan 所需要的Bitmap尺寸是不同的,通常是边框需要的Bitmap略大于填充区所需要的Bitmap。
Freetype的设计,由于是一次Ft_load_glyp获得outlineSpans 和 fillSpans, 所以可以猜想,他们的坐标系统是统一的,也就是说原点(0,0)点是重合的, 这也是为什么x, y 有时会出现负数的原因。
这个span啥的有个好处,实际上有了这个span, 基本上就可以脱离freetype的接口自己画文字了。当然他应该还有更raw的东西,目前没考虑要接触。
为了证实猜想,我首先做了一个测试。
打印出字符'g'的outlineSpans 和 fillSpans的数据.
其结果显示如下:
[2.24 19:55:11] [INFO] there are 94 span in fill rect. [2.24 19:55:11] [INFO] [0] x:2 y:-5 width:1 gray8:38 [2.24 19:55:11] [INFO] [1] x:3 y:-5 width:1 gray8:163 [2.24 19:55:11] [INFO] [2] x:4 y:-5 width:1 gray8:232 [2.24 19:55:11] [INFO] [3] x:5 y:-5 width:1 gray8:251 [2.24 19:55:11] [INFO] [4] x:6 y:-5 width:1 gray8:232 [2.24 19:55:11] [INFO] [5] x:7 y:-5 width:1 gray8:179 [2.24 19:55:11] [INFO] [6] x:8 y:-5 width:1 gray8:74 [2.24 19:55:11] [INFO] [7] x:2 y:-4 width:1 gray8:245 [2.24 19:55:11] [INFO] [8] x:3 y:-4 width:6 gray8:255 [2.24 19:55:11] [INFO] [9] x:9 y:-4 width:1 gray8:134 [2.24 19:55:11] [INFO] [10] x:2 y:-3 width:1 gray8:225 [2.24 19:55:11] [INFO] [11] x:3 y:-3 width:1 gray8:103 [2.24 19:55:11] [INFO] [12] x:4 y:-3 width:1 gray8:25 [2.24 19:55:11] [INFO] [13] x:5 y:-3 width:1 gray8:6 [2.24 19:55:11] [INFO] [14] x:6 y:-3 width:1 gray8:42 [2.24 19:55:11] [INFO] [15] x:7 y:-3 width:1 gray8:158 [2.24 19:55:11] [INFO] [16] x:8 y:-3 width:2 gray8:255 [2.24 19:55:11] [INFO] [17] x:10 y:-3 width:1 gray8:63 [2.24 19:55:11] [INFO] [18] x:2 y:-2 width:1 gray8:12 [2.24 19:55:11] [INFO] [19] x:8 y:-2 width:1 gray8:168 [2.24 19:55:11] [INFO] [20] x:9 y:-2 width:1 gray8:255 [2.24 19:55:11] [INFO] [21] x:10 y:-2 width:1 gray8:167 [2.24 19:55:11] [INFO] [22] x:8 y:-1 width:1 gray8:59 [2.24 19:55:11] [INFO] [23] x:9 y:-1 width:1 gray8:255 [2.24 19:55:11] [INFO] [24] x:10 y:-1 width:1 gray8:223 [2.24 19:55:11] [INFO] [25] x:2 y:0 width:1 gray8:16 [2.24 19:55:11] [INFO] [26] x:3 y:0 width:1 gray8:147 [2.24 19:55:11] [INFO] [27] x:4 y:0 width:1 gray8:230 [2.24 19:55:11] [INFO] [28] x:5 y:0 width:1 gray8:247 [2.24 19:55:11] [INFO] [29] x:6 y:0 width:1 gray8:206 [2.24 19:55:11] [INFO] [30] x:7 y:0 width:1 gray8:80 [2.24 19:55:11] [INFO] [31] x:8 y:0 width:1 gray8:13 [2.24 19:55:11] [INFO] [32] x:9 y:0 width:1 gray8:255 [2.24 19:55:11] [INFO] [33] x:10 y:0 width:1 gray8:247 [2.24 19:55:11] [INFO] [34] x:1 y:1 width:1 gray8:8 [2.24 19:55:11] [INFO] [35] x:2 y:1 width:1 gray8:207 [2.24 19:55:11] [INFO] [36] x:3 y:1 width:4 gray8:255 [2.24 19:55:11] [INFO] [37] x:7 y:1 width:1 gray8:254 [2.24 19:55:11] [INFO] [38] x:8 y:1 width:1 gray8:88 [2.24 19:55:11] [INFO] [39] x:9 y:1 width:2 gray8:255 [2.24 19:55:11] [INFO] [40] x:11 y:1 width:0 gray8:248 [2.24 19:55:11] [INFO] [41] x:1 y:2 width:1 gray8:119 [2.24 19:55:11] [INFO] [42] x:2 y:2 width:1 gray8:255 [2.24 19:55:11] [INFO] [43] x:3 y:2 width:1 gray8:247 [2.24 19:55:11] [INFO] [44] x:4 y:2 width:1 gray8:108 [2.24 19:55:11] [INFO] [45] x:5 y:2 width:1 gray8:21 [2.24 19:55:11] [INFO] [46] x:6 y:2 width:1 gray8:24 [2.24 19:55:11] [INFO] [47] x:7 y:2 width:1 gray8:113 [2.24 19:55:11] [INFO] [48] x:8 y:2 width:1 gray8:227 [2.24 19:55:11] [INFO] [49] x:9 y:2 width:2 gray8:255 [2.24 19:55:11] [INFO] [50] x:1 y:3 width:1 gray8:205 [2.24 19:55:11] [INFO] [51] x:2 y:3 width:1 gray8:255 [2.24 19:55:11] [INFO] [52] x:3 y:3 width:1 gray8:120 [2.24 19:55:11] [INFO] [53] x:8 y:3 width:1 gray8:114 [2.24 19:55:11] [INFO] [54] x:9 y:3 width:2 gray8:255 [2.24 19:55:11] [INFO] [55] x:1 y:4 width:1 gray8:244 [2.24 19:55:11] [INFO] [56] x:2 y:4 width:1 gray8:255 [2.24 19:55:11] [INFO] [57] x:3 y:4 width:1 gray8:31 [2.24 19:55:11] [INFO] [58] x:8 y:4 width:1 gray8:25 [2.24 19:55:11] [INFO] [59] x:9 y:4 width:2 gray8:255 [2.24 19:55:11] [INFO] [60] x:1 y:5 width:1 gray8:250 [2.24 19:55:11] [INFO] [61] x:2 y:5 width:1 gray8:255 [2.24 19:55:11] [INFO] [62] x:3 y:5 width:1 gray8:9 [2.24 19:55:11] [INFO] [63] x:9 y:5 width:2 gray8:255 [2.24 19:55:11] [INFO] [64] x:1 y:6 width:1 gray8:228 [2.24 19:55:11] [INFO] [65] x:2 y:6 width:1 gray8:255 [2.24 19:55:11] [INFO] [66] x:3 y:6 width:1 gray8:41 [2.24 19:55:11] [INFO] [67] x:8 y:6 width:1 gray8:10 [2.24 19:55:11] [INFO] [68] x:9 y:6 width:2 gray8:255 [2.24 19:55:11] [INFO] [69] x:1 y:7 width:1 gray8:172 [2.24 19:55:11] [INFO] [70] x:2 y:7 width:1 gray8:255 [2.24 19:55:11] [INFO] [71] x:3 y:7 width:1 gray8:141 [2.24 19:55:11] [INFO] [72] x:8 y:7 width:1 gray8:83 [2.24 19:55:11] [INFO] [73] x:9 y:7 width:2 gray8:255 [2.24 19:55:11] [INFO] [74] x:1 y:8 width:1 gray8:68 [2.24 19:55:11] [INFO] [75] x:2 y:8 width:1 gray8:255 [2.24 19:55:11] [INFO] [76] x:3 y:8 width:1 gray8:252 [2.24 19:55:11] [INFO] [77] x:4 y:8 width:1 gray8:128 [2.24 19:55:11] [INFO] [78] x:5 y:8 width:1 gray8:32 [2.24 19:55:11] [INFO] [79] x:6 y:8 width:1 gray8:16 [2.24 19:55:11] [INFO] [80] x:7 y:8 width:1 gray8:91 [2.24 19:55:11] [INFO] [81] x:8 y:8 width:1 gray8:235 [2.24 19:55:11] [INFO] [82] x:9 y:8 width:2 gray8:255 [2.24 19:55:11] [INFO] [83] x:2 y:9 width:1 gray8:147 [2.24 19:55:11] [INFO] [84] x:3 y:9 width:5 gray8:255 [2.24 19:55:11] [INFO] [85] x:8 y:9 width:1 gray8:142 [2.24 19:55:11] [INFO] [86] x:9 y:9 width:2 gray8:255 [2.24 19:55:11] [INFO] [87] x:3 y:10 width:1 gray8:100 [2.24 19:55:11] [INFO] [88] x:4 y:10 width:1 gray8:205 [2.24 19:55:11] [INFO] [89] x:5 y:10 width:1 gray8:246 [2.24 19:55:11] [INFO] [90] x:6 y:10 width:1 gray8:231 [2.24 19:55:11] [INFO] [91] x:7 y:10 width:1 gray8:132 [2.24 19:55:11] [INFO] [92] x:8 y:10 width:1 gray8:3 [2.24 19:55:11] [INFO] [93] x:9 y:10 width:2 gray8:255 [2.24 19:55:11] [INFO] fill rect :(0.000000,-5.000000) - (11.000000,10.000000), w:12.000000, h:16.000000 [2.24 19:55:11] [INFO] --------------------------------------------------- [2.24 19:55:11] [INFO] there are 91 span in outline rect. [2.24 19:55:11] [INFO] [0] x:2 y:-6 width:1 gray8:70 [2.24 19:55:11] [INFO] [1] x:3 y:-6 width:1 gray8:178 [2.24 19:55:11] [INFO] [2] x:4 y:-6 width:1 gray8:235 [2.24 19:55:11] [INFO] [3] x:5 y:-6 width:1 gray8:250 [2.24 19:55:11] [INFO] [4] x:6 y:-6 width:1 gray8:233 [2.24 19:55:11] [INFO] [5] x:7 y:-6 width:1 gray8:185 [2.24 19:55:11] [INFO] [6] x:8 y:-6 width:1 gray8:97 [2.24 19:55:11] [INFO] [7] x:9 y:-6 width:1 gray8:5 [2.24 19:55:11] [INFO] [8] x:1 y:-5 width:1 gray8:139 [2.24 19:55:11] [INFO] [9] x:2 y:-5 width:7 gray8:255 [2.24 19:55:11] [INFO] [10] x:9 y:-5 width:1 gray8:207 [2.24 19:55:11] [INFO] [11] x:10 y:-5 width:1 gray8:28 [2.24 19:55:11] [INFO] [12] x:1 y:-4 width:1 gray8:252 [2.24 19:55:11] [INFO] [13] x:2 y:-4 width:8 gray8:255 [2.24 19:55:11] [INFO] [14] x:10 y:-4 width:1 gray8:202 [2.24 19:55:11] [INFO] [15] x:11 y:-4 width:1 gray8:4 [2.24 19:55:11] [INFO] [16] x:1 y:-3 width:10 gray8:255 [2.24 19:55:11] [INFO] [17] x:11 y:-3 width:1 gray8:86 [2.24 19:55:11] [INFO] [18] x:1 y:-2 width:1 gray8:225 [2.24 19:55:11] [INFO] [19] x:2 y:-2 width:1 gray8:246 [2.24 19:55:11] [INFO] [20] x:3 y:-2 width:1 gray8:128 [2.24 19:55:11] [INFO] [21] x:4 y:-2 width:1 gray8:30 [2.24 19:55:11] [INFO] [22] x:5 y:-2 width:1 gray8:11 [2.24 19:55:11] [INFO] [23] x:6 y:-2 width:1 gray8:66 [2.24 19:55:11] [INFO] [24] x:7 y:-2 width:1 gray8:221 [2.24 19:55:11] [INFO] [25] x:8 y:-2 width:3 gray8:255 [2.24 19:55:11] [INFO] [26] x:11 y:-2 width:1 gray8:173 [2.24 19:55:11] [INFO] [27] x:1 y:-1 width:1 gray8:19 [2.24 19:55:11] [INFO] [28] x:2 y:-1 width:1 gray8:70 [2.24 19:55:11] [INFO] [29] x:3 y:-1 width:1 gray8:171 [2.24 19:55:11] [INFO] [30] x:4 y:-1 width:1 gray8:234 [2.24 19:55:11] [INFO] [31] x:5 y:-1 width:1 gray8:247 [2.24 19:55:11] [INFO] [32] x:6 y:-1 width:1 gray8:215 [2.24 19:55:11] [INFO] [33] x:7 y:-1 width:1 gray8:197 [2.24 19:55:11] [INFO] [34] x:8 y:-1 width:3 gray8:255 [2.24 19:55:11] [INFO] [35] x:11 y:-1 width:1 gray8:225 [2.24 19:55:11] [INFO] [36] x:1 y:0 width:1 gray8:81 [2.24 19:55:11] [INFO] [37] x:2 y:0 width:1 gray8:250 [2.24 19:55:11] [INFO] [38] x:3 y:0 width:8 gray8:255 [2.24 19:55:11] [INFO] [39] x:11 y:0 width:1 gray8:246 [2.24 19:55:11] [INFO] [40] x:0 y:1 width:1 gray8:29 [2.24 19:55:11] [INFO] [41] x:1 y:1 width:1 gray8:243 [2.24 19:55:11] [INFO] [42] x:2 y:1 width:10 gray8:255 [2.24 19:55:11] [INFO] [43] x:12 y:1 width:0 gray8:248 [2.24 19:55:11] [INFO] [44] x:0 y:2 width:1 gray8:139 [2.24 19:55:11] [INFO] [45] x:1 y:2 width:11 gray8:255 [2.24 19:55:11] [INFO] [46] x:0 y:3 width:1 gray8:211 [2.24 19:55:11] [INFO] [47] x:1 y:3 width:3 gray8:255 [2.24 19:55:11] [INFO] [48] x:4 y:3 width:1 gray8:177 [2.24 19:55:11] [INFO] [49] x:5 y:3 width:1 gray8:22 [2.24 19:55:11] [INFO] [50] x:6 y:3 width:1 gray8:25 [2.24 19:55:11] [INFO] [51] x:7 y:3 width:1 gray8:175 [2.24 19:55:11] [INFO] [52] x:8 y:3 width:4 gray8:255 [2.24 19:55:11] [INFO] [53] x:0 y:4 width:1 gray8:245 [2.24 19:55:11] [INFO] [54] x:1 y:4 width:3 gray8:255 [2.24 19:55:11] [INFO] [55] x:4 y:4 width:1 gray8:34 [2.24 19:55:11] [INFO] [56] x:7 y:4 width:1 gray8:29 [2.24 19:55:11] [INFO] [57] x:8 y:4 width:4 gray8:255 [2.24 19:55:11] [INFO] [58] x:0 y:5 width:1 gray8:250 [2.24 19:55:11] [INFO] [59] x:1 y:5 width:3 gray8:255 [2.24 19:55:11] [INFO] [60] x:4 y:5 width:1 gray8:9 [2.24 19:55:11] [INFO] [61] x:8 y:5 width:4 gray8:255 [2.24 19:55:11] [INFO] [62] x:0 y:6 width:1 gray8:230 [2.24 19:55:11] [INFO] [63] x:1 y:6 width:3 gray8:255 [2.24 19:55:11] [INFO] [64] x:4 y:6 width:1 gray8:48 [2.24 19:55:11] [INFO] [65] x:7 y:6 width:1 gray8:9 [2.24 19:55:11] [INFO] [66] x:8 y:6 width:4 gray8:255 [2.24 19:55:11] [INFO] [67] x:0 y:7 width:1 gray8:181 [2.24 19:55:11] [INFO] [68] x:1 y:7 width:3 gray8:255 [2.24 19:55:11] [INFO] [69] x:4 y:7 width:1 gray8:191 [2.24 19:55:11] [INFO] [70] x:5 y:7 width:1 gray8:34 [2.24 19:55:11] [INFO] [71] x:6 y:7 width:1 gray8:17 [2.24 19:55:11] [INFO] [72] x:7 y:7 width:1 gray8:149 [2.24 19:55:11] [INFO] [73] x:8 y:7 width:4 gray8:255 [2.24 19:55:11] [INFO] [74] x:0 y:8 width:1 gray8:93 [2.24 19:55:11] [INFO] [75] x:1 y:8 width:11 gray8:255 [2.24 19:55:11] [INFO] [76] x:0 y:9 width:1 gray8:5 [2.24 19:55:11] [INFO] [77] x:1 y:9 width:1 gray8:207 [2.24 19:55:11] [INFO] [78] x:2 y:9 width:10 gray8:255 [2.24 19:55:11] [INFO] [79] x:1 y:10 width:1 gray8:32 [2.24 19:55:11] [INFO] [80] x:2 y:10 width:1 gray8:222 [2.24 19:55:11] [INFO] [81] x:3 y:10 width:9 gray8:255 [2.24 19:55:11] [INFO] [82] x:2 y:11 width:1 gray8:13 [2.24 19:55:11] [INFO] [83] x:3 y:11 width:1 gray8:126 [2.24 19:55:11] [INFO] [84] x:4 y:11 width:1 gray8:212 [2.24 19:55:11] [INFO] [85] x:5 y:11 width:1 gray8:246 [2.24 19:55:11] [INFO] [86] x:6 y:11 width:1 gray8:230 [2.24 19:55:11] [INFO] [87] x:7 y:11 width:1 gray8:159 [2.24 19:55:11] [INFO] [88] x:8 y:11 width:1 gray8:212 [2.24 19:55:11] [INFO] [89] x:9 y:11 width:2 gray8:255 [2.24 19:55:11] [INFO] [90] x:11 y:11 width:1 gray8:180 [2.24 19:55:11] [INFO] outline rect :(0.000000,-6.000000) - (12.000000,11.000000), w:13.000000, h:18.000000 [2.24 19:55:11] [INFO] overlapped rect :(0.000000,-6.000000) - (12.000000,11.000000), w:13.000000, h:18.000000由此可以得到:
填充区一共有94个span, 分布在坐标左上(0,-5) 右下(11,10) , 其矩形区域尺寸为(12,16)
沟边区一共有91个span, 分别在(0, -6) (12,11) 其矩形区域尺寸为(13,18)
填充与沟边的合成位图最终需要尺寸(13, 18)
妈呀,一个g 有94 + 91 = 185个span 只是一个g.
但是鉴于计算机处理的速度比我快,所以先忽略继续往下走起。
范例中,设置颜色到bitmap的代码是:
charBitmap[(int)((imgHeight - 1 - (s->y - rect.ymin)) * imgWidth + s->x - rect.xmin + w)] = outLineColor;
所以Bitmap 与 fillRect的坐标映射关系是:
y = (imgHeight - 1 - (s->y - rect.ymin)) * imgWidth
x = s->x - rect.xmin
实际上是完成形如下图的坐标变换:
那么实际上,可以较为轻松的分别保存outlineBitmap 和 fillBitmap , 用于存储灰度.并记录offsetX, offsetY 作为坐标参考系对齐的依据。
但是,后来回过头来考虑这个问题,我干嘛要分别存储2个bitmap, 难道是像复用fillBitmap么? 没有啊,所以我不用分别存储outlineBitmap和fillBitmap,仅需要存储一个总的bitmap, 其大小是outline rect 和 fill rect 的bound rect.然后将两个灰度存入就行了。实际上,由于很多设备不支持2通道纹理,这里我选择采用RGBA8888的格式存储, R通道存储填充灰度, G通道存储边框灰度。浪费了2个通道实在属于无奈之举,但shader可以直接拿到这个texture做渲染,也是件好事。
除了bitmap需要关注,还需要取得相关的char metrics 并缓存下来, 因为Layout逻辑需要用到这些位置相关的数据。具体需要的值参考下图:
另需要注意的是,由于对边框的支持, 所以可能会对一些位置数据进行修正。
需要修正的数据包括:
bearingX, bearingY, width, height, advance.
如果不调整会这样?那么在字符有边框的时候,后面的字符很可能把前面的盖住。
怎么调整呢,嗯,嗯。直接写代码调整,对。
所以整理下载,缓存的结构体大概是这样的:
CharChache
bitmap : 纹理位图(r,g有用处, b,a 没用, 也许将来可以写点啥在里面)
charMetrics
-bearingX
-bearingY
-advance
-width
-height
那么缓存的Key怎么考虑呢
Key包含一下部分:
char (uint16) 字符的unicode
font_size(uint8)
outline_size(unit8)
font_size 和 outline_size 采用uint8的原因是, 这样可以用一个32位整形数来作为缓存对象的键值,使用超过一个字节的情况存储font_size 和 outline_size 不做考虑,因为那种情况太极端了。
剩下的工作就相当的轻松了.我可以把大致需要的接口做个列表:
void renderString(string _str, TextStyle _defaultStyle, Texture2D _outTexture)
这个是整个文字渲染的进入点接口, 可以按Factory模式处理,目前实现FreeTypeWithBitmapCache 实现, 将来还可以搞个Device 实现,直接向操作系统要纹理,比如ios本身似乎是支持包边字体纹理生成的。
_defaultStyle 参数是文本的样式参数,包含行间距,字符间距,是否换行,换行宽度,首行indent,字体颜色, 边框颜色等信息.
总之,这个接口就是我把字符串给你,你按我要的效果给生成纹理。
void htmlParse(string _str, HtmlTagList _outHtmlTagList, string _outPureString)
该方法是解析富文本字符串(其实不是html,算是一种私有协议)。
输出的HtmlTagList 是解析的结果,他不是一颗树,实际只是一个链表而已(不想做那么复杂, 因为我压根就没打算支持标签的嵌套,简单实现即可,不必搞成浏览器,如果策划问为啥不支持嵌套表格,文本输入框, 嵌图片,为啥没有播放音频功能,直接耳屎扇飞)。
_outPureString 是纯文本的内容,实际也可以通过_outHtmlList 分析得到,但是这个方法输出来,作为顺便完成的工作.
ChatCacheEntry* queryCharCache(wchar _ch, uint8 _fontSize, _unit8 _outlineSize)
查询缓存, 如果缓存中不存在, 则按之前分析的逻辑生成ChatCacheEntry。
这里还有一个可优化的地方.就是可以在ChatCacheEntry中存放一个命中次数,内部按该次数对ChatChacheEntry进行排序,在适当的时候删除掉低命中次数的缓存条目,这样可以避免文字缓存把内存搞爆的情况。
void layout(string _str, TextStyle _style, vector<CharMetrics> _metrics, vector<Point> _outPos)
该方法接受字符串,样式,以及与字符串对应的每个字符的metrcis信息,该方法对整个字符串进行布局,并将位置输出到_outPos中。
始终 _str.length = _metrics.size = _outPos.size
所以最核心的方法就是上述这些。
其中客户端真正调用的就是 renderString, 其他接口都是为renderString服务,在renderString内部被调用的。
最后就是shader
shader很简单,
传入 fillColor, outlineColor
传入 纹理 texture
那么pixel颜色为
outlineColor.rgb = outlineColor.rgb
outlineColor.a = texture.r
outColor.rgb = outlineColor.rgb + (fillColor.rgb - outlineColor.rgb) * texture.g
outColor.a = outlineColor.a + texture.g
然后,就基本上没有然后了。
云风有篇博文提到了一种方案,提出直接用一张大texture 作为文字的缓存。有兴趣可以去看下,不过我基于以下原因暂时不打算采用。
其一:这一版本我的目标仅是性能足够而非性能最优。
其二:大纹理并且随着新字符的生成和老字符的移除,同样会涉及主存和显存的换入换出,如果更新频繁,该方案是否总体上有益不能确定。
其三:我们的系统font_size 的尺寸不好估量12pt 和 24pt有可能都有,涉及到装箱算法,如果单页满了,还可能会做multi paging , 总的来说可能会增加大量复杂度。
东西一复杂了我就拉不出屎了。先看看吧,先看看。
所以目前还是先简单实现一版,看看性能如何再说。
该文档。。那啥,主要是整理自己的思路写下的日志和开发参考,大量细节都省略。所以估计很难阅读。也可能有超多的错漏。
嗯,嗯,明天开始编码。
现在先去看行尸走肉
LOG.ZS.0001.基于Freetype的游戏字体渲染优化思路的更多相关文章
- win10 字体渲染优化 色彩调整
最近烧包买了个2k显示器,发现跟win10使用,一堆问题,最大的就是字体,其实应该买4k,那样正好设置200%字体,现在设置的124% 字体: 以前使用的是mactype这个软件 https://pa ...
- Atitit 基于dom的游戏引擎
Atitit 基于dom的游戏引擎 1. 添加sprite控件(cocos,createjs,dom)1 1.1.1. Cocos1 1.1.2. createjs1 1.1.3. Dom模式2 1. ...
- 使用FreeType实现矢量字体的粗体、斜体、描边、阴影效果
前言: Freetype是一个跨平台.开源的字体渲染器,网上很多文章介绍,本人就不啰嗦了.本文重点在于实现文章标题所属的各种效果,不是Freetype的基本使用方法介绍文档,所以对于Freetype不 ...
- Monotype推出基于HTML5的Web字体平台
著名字体公司Monotype近日宣布推出基于HTML5的Web字体平台,设计者可以访问近10万字体的目录. Monotype推出基于HTML5的Web字体平台 Monotype推出基于HTML5的We ...
- 基于cocos2d-x的游戏框架设计——李成
视频:http://v.youku.com/v_show/id_XMzc5ODUyMTI4.html?f=17330006 网易科技讯 3月31日,第四届CocoaChina开发者大会暨Cocos2d ...
- 基于 Cocos2d-x-lua 的游戏开发框架 Dorothy 简介
基于 Cocos2d-x-lua 的游戏开发框架 Dorothy 简介 概述 Dorothy 是一个在 Cocos2d-x-lua 基础上发展起来的分支, 它去掉 Cocos2d-x-lua 那些过多 ...
- (14)如何使用Cocos2d-x 3.0制作基于tilemap的游戏:第二部分
引言 程序截图: 这篇教程是<如何使用Cocos2d-x 3.0制作基于tilemap的游戏>的第二部分.在上一个教程中,我们创建了一个简单的基于tiled地图的游戏,里面有一个忍者在沙漠 ...
- 基于Lua的游戏服务端框架简介
基于Lua的游戏服务端框架简介 [转]https://gameinstitute.qq.com/community/detail/106396 基于lua的游戏服务端框架简介 1. 引言 笔者目前在参 ...
- Fedora 24 Linux 环境下实现 Infinality 字体渲染增强及 Java 字体渲染改善的方法(修订)
Fedora 24 Linux 桌面环境默认字体渲染引擎 freetype 及字体配置工具 fontconfig 采用的是未经优化的编译及设置,字体渲染效果比较差.而某些 Linux 发行版的桌面字体 ...
随机推荐
- 【Java TCP/IP Socket】深入剖析socket——数据传输的底层实现
底层数据结构 如果不理解套接字的具体实现所关联的数据结构和底层协议的工作细节,就很难抓住网络编程的精妙之处,对于TCP套接字来说,更是如此.套接字所关联的底层的数据结构集包含了特定Socket实例所关 ...
- 【Java TCP/IP Socket】构建和解析自定义协议消息(含代码)
在传输消息时,用Java内置的方法和工具确实很用,如:对象序列化,RMI远程调用等.但有时候,针对要传输的特定类型的数据,实现自己的方法可能更简单.容易或有效.下面给出一个实现了自定义构建和解析协议消 ...
- SystemTap使用技巧 1 - 4 非常重要
http://blog.csdn.net/wangzuxi/article/details/42849053
- python遍历两个列表,若长度不等,用None填充
zip经常会遇到截断问题,如:a = [1,2,3], b = [4,5,6,7],则zip(a,b) = [(1, 4), (2, 5), (3, 6)] 可考虑使用map: map(lambda ...
- 转: 环信联合创始人:App主流反垃圾服务难点和技术实现全解析
转:http://science.china.com.cn/2016-03/24/content_8659834.htm 发布时间: 2016-03-24 13:15:02 | 来源: 全球财经网 ...
- NGUI UIScrollView - 大量item子项的性能优化
一.当UIScrollView的以下的包括的子项太多(二三十个之上)时.它的滚动就会变的有些卡不流畅,尤其是在手机上. 对些网上也有非常多的优化它的相关,以下是我的一个优化: 1.将在超出裁剪框的一个 ...
- mysql 复制数据库
为了方便快速复制一个数据库,可以用以下命令 将db1数据库的数据以及表结构复制到newdb数据库 创建新的数据库 #mysql -u root -p123456 mysql>CREATE DAT ...
- 模拟 nbut1225 NEW RDSP MODE I
传送门:点击打开链接 题意:输入n.m,x.刚開始有一个1~n的排列.然后定义了一种操作.是将数组中的偶数位数字选出来,依照顺序放到数组最前面,奇数位依照顺序放到偶数位的后面,进行m次这种操作.输出之 ...
- 关于数组类型的json解析方法
遇到了非常奇葩的数组类型的json,一时解析不出来,用jsonObject会直接报错. Json数据如: [{"id":"1000142","name ...
- openwrt 实现hotplug-button
<*> kmod-gpio-button-hotplug................Simple GPIO Button Hotplug driver gpio-button-hotp ...