高质量文本渲染

highquality_textrendering_04highquality_textrendering_03highquality_textrendering_02highquality_textrendering_01

目标

在实时 3D 图形中尽可能保持最高质量的文本极富挑战。对象的位置、旋转、缩放以及视角都可能发生动态变化。所有这些都对质量造成负面影响,因为文本通常只生成一次,而不是每一帧都生成。为整个文本生成纹理非常耗时,具体取决于字体引擎及其性能。这一时长通常足以让性能下滑。

本文演示了一种在对象为半动态时尽可能获得最佳文本质量的方式。半动态对象只是一个对象,它不会经常变化(并非每一帧),也不会在动画时间中改变。

 

概述

本白皮书介绍如何计算字体大小,其应当可将纹素紧密匹配至屏幕像素。

我们将使用属于 Android 一部分的字体引擎。该字体引擎产生包含整个文本形状的 RGBA 图像。接着该图像上传到纹理中,而后纹理再映射到矩形上。该矩形几何体必须根据纹理大小定义适当的纵横比。

 

估算字体大小

要估算对象当前转换的字体大小,我们需要将矩形的四个角从 3D 世界空间转换到 2D 像素屏幕空间。以像素表示角后,我们可以计算两个左角之间的距离,以及两个右角之间的距离。然后根据这两个距离计算平均值。平均值正是我们要找到的,它就是我们要用于生成图像的字体大小。

以下是 Vector4f 类中 makePixelCoords 方法的定义。该方法将 3D 顶点位置转换为 2D 像素位置。

 

纹理生成

由于我们已经知道字体大小,因此可以估计目标图像的大小。图像必须足够大,能够存储整个文本且无任何截断。另一方面,它也不能太大,因为后续的几何计算以图像大小为基础。我们希望这一大小刚好适合字体引擎将要生成的内容。

高度计算比较简单,因为这就是字体的尺寸;但宽度就非常复杂了。要正确计算宽度,需要使用字体引擎来帮助我们进行估计。Android Java SDK 在 Paint 对象中附带了 measureText 方法。在执行测量之前,我们需要将所有必要的数据传送给该对象,例如:字体名称、字体大小(已经计算出)、抗锯齿、颜色 ARGB(此情形中始终为白色,因为以后可在片段着色器中进行上色),以及其他较不重要的数据。

在将文本绘制到位图对象前,我们需要使用白色(Alpha 值为完全透明 ARGB = (0, 255, 255, 255))来清除其内容。通过使用此颜色清除背景并将绘制颜色也设为白色,可以防止 α 混合可能导致的暗纹素。谈到混合的话,就务必要提一下 GL 混合函数,必须正确设置该函数,然后再渲染文本。该混合函数必须设为:glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)

下面的函数执行上述所有步骤:

 

进一步改进
  1. 如果您的程序中文本经常变化,那么此概念可能也会适合。我们建议创建一个独立的线程,它将以一定间隔持续更新相关纹理。在大多数情形中,最需要的是将该线程维持在尽可能最低的优先级上,因为生成文本总是被视为重量级运算,很有可能导致性能降级。不言而喻,更新纹理应当在服务于 GL 上下文的线程上执行。
  2. 如果您要沿着贝塞尔曲线渲染文本,或者要进行一些位移,您需要更加精准地估计字体大小。为此,还要增加矩形的水平分辨率。此时,矩形将分割为垂直切面。然后,估算所有这些切面的平均高度。其平均高度值用于提高字体大小的精度。



原文:http://malideveloper.arm.com/cn/develop-for-mali/sample-code/%E9%AB%98%E8%B4%A8%E9%87%8F%E6%96%87%E6%9C%AC%E6%B8%B2%E6%9F%93/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值