如何为 OpenGL 文本渲染计算字符映射中的最佳字形边界

Posted

技术标签:

【中文标题】如何为 OpenGL 文本渲染计算字符映射中的最佳字形边界【英文标题】:How to calculate the optimal glyph bounds in a character map for OpenGL text rendering 【发布时间】:2014-07-30 23:02:22 【问题描述】:

为了使用 OpenGL 渲染文本,我采用带纹理的四边形方法,为每个需要表示的字符绘制一个四边形。我将所有字符纹理信息存储在单个纹理中,并在纹理矩阵上使用 glScalef 和 glTranslatef 来选择纹理中的正确字符。起初我只在用于创建纹理的图像中放置了几个字符,并且效果很好。

从那时起,我需要渲染更多字符,例如小写字母。我尝试添加更多字符,但现在我的文本未对齐且更小。

是否有正确的方法来创建角色映射,或者我的方法都错了?

注意:我使用的是单一样式的字体,所以字体尺寸不应该是问题,但是我想添加对具有非统一大小字符的字体的支持。

编辑:我使用顶点缓冲区进行绘图而不是立即模式。

编辑 2:包含字符映射的纹理有 9 行,每行有 11 个字符。由于字符大小相同,所以我在纹理矩阵上使用 glscalef 到纹理宽度的 1/9,高度的 1/11。 VBO 定义四边形 (0,0),(1,0),(0,1),(1,1) 和 tex 坐标 (0,0),(1,0),(0,1),( 1,1)。不对齐似乎是由于我的转换不完全适合每个字形。如何计算每个字形的最佳边界?

【问题讨论】:

您应该只为每个四边形生成适当的纹理坐标,而不是 glScalef glTransform(无论如何都已弃用)。 我正在尝试将所需的 OpenGL 版本保持在尽可能低的水平,因此我使用了这些功能。我确实有字符映射上字符的坐标,如果这也是您所指的,但它基于每个字符相对于字符映射大小的统一大小。这个尺寸被 OpenGL 标准化为 1:1。 段落的后半部分没有太多意义。正如 datenwolf 所说,设置四边形的纹理坐标(使用glTexCoord2d 或类似的)而不是弄乱纹理矩阵。 对不起,我应该提到我正在使用顶点缓冲区进行绘图而不是立即模式,部分原因是它很容易移植到 OpenGL ES。 @Josh:那还是没有道理,不是简单地调整纹理坐标。纹理坐标不是现代 OpenGL 的一些特性。自从纹理被引入以来,它们就一直是 OpenGL 的一部分,这在 20 多年前发生在 OpenGL-1.0 中。您肯定会为您的顶点缓冲区提供纹理坐标数组。这就是角色纹理坐标所在的位置。 【参考方案1】:

希望这对其他人有用。最佳字形边界可以通过首先标准化每个字母的像素偏移量来计算,使它们是 0 和 1 范围内的数字。宽度和高度也可以标准化以确定正确的边界框。如果宽度和高度是统一的,例如在单声道字体中,则可以使用静态宽度和高度值来计算字形边界。

为每个字形保存一组像素位置值手动计算会很繁琐,因此最好在字符映射的第一个像素处开始第一个字形,并且每个字母之间没有间距。这将使使用 for 循环轻松计算左下角 uv 坐标

void GetUVs(Vector2* us, Vector2* vs, float charWidth, float charHeight, int cols, int rows)

    for (int x = 0; x < cols; x++)
    
        for (int y = 0; y < rows; y++)
        
            int index = x + cols * y;
            us[index].x = x * charWidth;
            vs[index].y = y * charHeight;
        
    

其余的边界可以通过分别添加宽度、高度以及宽度和高度来计算。

【讨论】:

以上是关于如何为 OpenGL 文本渲染计算字符映射中的最佳字形边界的主要内容,如果未能解决你的问题,请参考以下文章

基于OpenGL编写一个简易的2D渲染框架-05 渲染文本

tkinter - 如何为文本设置字体?

◮OpenGL-文本渲染

如何为css中的文本设置特定的像素或字符宽度限制

◮OpenGL-文本渲染

渲染镶嵌对象的最佳方式 (OpenGL)