3

我正在为 OpenGL 应用程序编写文本渲染器。大小、颜色、字体和抗锯齿可以在运行时调整(因此多个字体可以同时出现在屏幕上)。组合太多,无法为字符串和属性的每个组合分配一个纹理。但是,在任何给定时间,整个字符串数据库中只有一小部分会出现在屏幕上。

这使我有机会为逐帧打印的字符串创建缓存。强制要求我在整个操作中只使用一个纹理,因为创建许多纹理的缓存会导致从缓存中打印的每个不同字符串的纹理交换惩罚。

所以我面前有一个 2048x2048 的纹理,我可以在其中放置我可以容纳的任何字符串,因为应用程序出于缓存目的请求它们。我很快意识到跟踪二维空间中的可用空间并非易事。

我一直在研究诸如 Best Fit 和 Next fit 之类的东西,但它们似乎适合一维空间。

如何在 OpenGL 中管理这个缓存纹理?

编辑:从那以后,我了解到这是“2d 打包问题”的一个实例。

4

3 回答 3

2

你所拥有的是装箱问题。

首先是坏消息:它是 NP 难的,因此值得找到最佳解决方案。

我也为字体做了这样的纹理缓存。我没有缓存整个单词,而只是缓存了字形图像。这让事情变得容易多了,因为你所有的图像都是大致方形的。一种简单的基于网格的方法来跟踪纹理内存效果很好。

如果我得到的字形大于我的一个网格框,我只需使用蛮力搜索分配两个或更多框(这种情况并不经常发生)。如果我没有找到任何合适的块,我只是从缓存中随机删除一些字形以腾出空间。

这比将东西保存在最近使用的缓存中要容易得多,而且性能几乎一样好。

顺便说一句 - 对于这样的缓存,您总是会浪费一些纹理内存。除非您的内存非常紧张,否则这应该不是问题。您应该使用小的纹理格式(8 位 alpha 非常适合字体)。

另外:如果您将网格块设置为 8 像素的倍数,并且可以将抗锯齿降低到 4 位,则可以动态地将字形压缩为压缩的 DXT 或 S3TC 格式之一。这样,浪费的纹理空间就不是问题了。

于 2009-03-27T03:39:49.253 回答
1

如果您的纹理内存不足,您可以查看“距离场”或“有符号距离场”字体渲染技术。您可以为每个字体系列使用 512x512 纹理,并且可以渲染任何大小的完美抗锯齿文本。

对于该算法,您需要生成一个特殊的纹理,其中包含从纹素到纹理边缘的距离。看看 Valve 人的原始论文:http ://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf 。有一些框架利用了这一点。例如,最新版本的 Qt 使用有符号距离字段进行文本渲染。

于 2012-07-15T16:15:29.500 回答
0

我选择使用一种简单的方法。将纹理划分为可变高度行。放置在一行中的第一个纹理决定了行的高度。如果纹理可以按高度放入现有行,请检查是否有足够的宽度剩余并将其放置在那里。否则开始一个新行。如果无法启动新行,则不要缓存字符串。

于 2009-03-31T17:47:03.300 回答