OpenGLES 2中的文本/字体渲染(iOS - CoreText?) - 选项和最佳实践?

Ada*_*dam 18 fonts core-animation opengl-es core-text ios

关于OpenGL字体渲染有很多问题,其中许多问题都是由纹理图集(快速但错误)或字符串纹理(仅限固定文本)所满足.

然而,这些方法很差,似乎已经过时了(使用着色器更好/更快地做到这一点怎么样?).对于OpenGL 4.1,有一个很好的问题,看看"你今天应该使用什么?":

从版本4.1开始,OpenGL中的文本渲染技术是什么?

那么,今天我们应该在iOS GL ES 2上使用什么?

我很失望,似乎没有开源(甚至是商业解决方案).我知道有很多团队把它搞砸了,花了几周的时间重新发明这个轮子,逐渐学习如何克服和空间等(呃) - 但必须有一个比重写整个"字体"更好的方法从头开始?


据我所知,这有两个部分:

  1. 我们如何使用字体渲染文字?
  2. 我们如何显示输出?

对于1(如何渲染),Apple提供了许多方法来获得"正确的"渲染输出 - 但"简单"的方法不支持OpenGL(也许其他一些方式 - 例如是否有一种简单的方法来映射CoreText输出到OpenGL?).

对于2(如何显示),我们有着色器,我们有VBO,我们有字形纹理,我们有查找纹理,以及其他tecniques(例如上面链接的OpenGL 4.1内容?)

以下是我所知道的两种常见的OpenGL方法:

  1. 纹理图集(渲染所有字形一次,然后从共享纹理渲染每个字符1 x纹理四边形)
    1. 这是错误的,除非你使用20世纪80年代的"位图字体"(即便如此:纹理图集需要比看似更多的工作,如果你需要它更正确的非平凡字体)
    2. (字体不是"字形的集合",有大量的定位,布局,包装,间距,字距,样式,着色,加权等.纹理图集失败)
  2. 固定字符串(使用任何Apple类正确渲染,然后截取背景图像数据,并上传为纹理)
    1. 从人的角度来说,这很快.在帧渲染中,这非常非常慢.如果您使用大量更改文本执行此操作,则帧速率会在整个范围内显示
    2. 从技术上讲,它大多是正确的(不完全是:你以这种方式丢失了一些信息)但效率极低

我也看过,但听到了好的和坏的事情:

  1. Imagination/PowerVR"Print3D"(链接坏了)(来自制造GPU的人!但是他们的网站移动/删除了文本渲染页面)
  2. FreeType(需要预处理,解释,大量代码,额外的库?)
  3. ...和/或FTGL http://sourceforge.net/projects/ftgl/(谣言:慢?错误?很长时间没有更新?)
  4. 字体存储http://digestingduck.blogspot.co.uk/2009/08/font-stash.html(高质量,但非常慢?)
  5. 1.

在Apple自己的OS /标准库中,我知道几种文本呈现源.注意:我已经在2D渲染项目中详细使用了大部分这些,我关于它们输出不同渲染的陈述是基于直接经验

  1. CoreGraphics与NSString
    1. 最简单的:渲染"进入CGRect"
    2. 似乎是人们推荐的"固定字符串"方法的稍微快一点的版本(即使你期望它大致相同)
  2. UILabel和UITextArea用纯文本
    1. NB:他们不一样!他们如何渲染smae文本略有不同
  3. NSAttributedString,呈现给上面的一个
    1. 再次:渲染方式不同(我所知道的差异相当微妙并被归类为"错误",关于此的各种SO问题)
  4. CATextLayer
    1. iOS字体和旧C渲染之间的混合体.使用"不完全"免费桥接的CFFont/UIFont,它揭示了一些更多的渲染差异/陌生感
  5. CoreText
    1. ......最终的解决方案?但是它自己的野兽......

Ada*_*dam 7

我做了一些实验,看起来CoreText在与纹理图集和Valve的符号差异纹理(可以将位图字形转换为独立于分辨率的高分辨率纹理)结合时可能会提供完美的解决方案.

......但我还没有工作,还在试验.


更新:Apple的文档说他们可以访问除最终细节之外的所有内容:要呈现的字形+字形布局(根据文档,您可以获得行布局,字形数量,但不能使用字形本身).由于没有明显的原因,CoreText显然缺少这个核心信息(如果是这样,那使CT几乎一文不值.我还在寻找能否找到实际glpyhs + per-glyph数据的方法)


UPDATE2:我现在已经正常使用Apple的CT(但没有不同的纹理),但它最终成为3个类文件,10个数据结构,大约300行代码,再加上OpenGL代码来渲染它.SO答案太多了:(.

简短的回答是:是的,你可以做到,如果你:

  1. 创建CTFrameSetter
  2. 为理论2D帧创建CTFrame
  3. 创建一个CGContext,您将转换为GL纹理
  4. 通过glyph-by-glyph,允许Apple渲染到CGContext
  5. 每次Apple渲染一个字形时,计算边界框(这是HARD),并将其保存在某个地方
  6. 并保存唯一的字形ID(例如"o","f"和"of"(一个字形!)会有所不同)
  7. 最后,将CGContext作为纹理发送到GL

渲染时,使用Apple创建的字形ID列表,并使用保存的信息和纹理,使用纹理协作渲染四边形,从而将单个字形拉出您上传的纹理.

这很有效,它很快,适用于所有字体,它可以获得所有字体布局和字距调整等.