代码之家  ›  专栏  ›  技术社区  ›  Kornel Kisielewicz

如何为图形用户界面进行OpenGL实时文本呈现?

  •  39
  • Kornel Kisielewicz  · 技术社区  · 14 年前

    我正在实现一个构建在OpenGL之上的GUI。我谈到了每个GUI都会遇到的问题——文本呈现。我知道在OpenGL中呈现文本的几种方法,但是,我很想知道哪种方法最适合图形用户界面。

    通常,在GUI中,我们有两种类型的文本——静态文本和活动文本。静态很容易——我们可以将TTF渲染为纹理,然后忽略它。更让我困扰的是“实时”文本——想象一下游戏机,或者多人游戏中的实时聊天。

    我想到了几个选择:

    • 没有特殊情况——每次文本更改时渲染和加载纹理,记住只有在实际出现新文本时才重新渲染纹理,并尝试将较大的文本拆分为小部分(如每个聊天行)。然而,这仍然会让我们在一些情况下绞尽脑汁,比如一条随时变化的分数线,或者一个呈现“每个字符”的介绍文本(在一些科幻游戏中看到的打字机样式)。
    • 每字符四元--这似乎也是一个流行的解决方案,您可以使用ASCII表准备纹理,并渲染纹理四元字符。然而,我对这种解决方案的效率有着严重的怀疑。还有一些小技巧,比如如何使速度更快。
    • 混合解决方案——但是我不知道如何实现它 干净利落

    因此,问题是——如何高效地在OpenGL中呈现文本?

    如果这有帮助,我在STL编码/Boost重C++,并瞄准G武力6和后来的显卡。

    7 回复  |  直到 6 年前
        1
  •  29
  •   Gregory Pakosz    12 年前

    伊迪丝2:肖恩·巴雷特刚刚发布 Bitmap fonts for C/C++ 3D programmers .

    编辑:另一个值得一看的代码宝石是 Font Stash 利用了肖恩·巴雷特的 stb_truetype.h .


    可以创建一个纹理,在该纹理中渲染字体的所有字符。然后用正交投影和适当的纹理坐标绘制纹理四边形:当文本使用的语言不包含太多符号(如英语)时,这种方法是有效的。字体纹理在应用程序开始时创建一次,然后渲染四边形非常快。

    这就是我正在使用的,我相信这是在OpenGL中呈现文本的最快方法。起初,我用 Angelcode's Bitmap Font Generator 工具,然后我集成 FreeType 直接构建一个包含应用程序启动时所有字形的大纹理。至于提高四边形渲染速度的技巧,我只是在应用程序的其余几何图形中使用了vbo。

    我很惊讶您对四重渲染有疑问,而您似乎不担心在CPU上生成纹理,然后上载纹理,然后绑定纹理,最后用它渲染一个矩形,即每个帧的纹理。更改OpenGL状态是瓶颈,而不是用于文本的500-1000夸脱。

    另外,看看图书馆 FTGL 将整个字体转换为多边形(几何字体)的库。

        2
  •  9
  •   luke    14 年前

    尝试阅读: http://dmedia.dprogramming.com/?n=Tutorials.TextRendering1 .

    所描述的方法是使用图形API呈现文本的典型方法。每个四元一个字符,以及单个纹理中文本的所有图像数据。如果可以将整个角色集调整为一个纹理(实际上,取决于纹理的大小,您可能可以调整多个纹理),则渲染速度非常快。

    关键是纹理绑定是您需要最小化的操作。如果你能用一个纹理渲染你所有的文本,你需要在屏幕上显示多少文本就无关紧要了。即使要多次切换纹理(不同的字体、不同的字体属性[粗体、下划线等]),性能也应该很好。文本性能对于HUD可能更为关键,但在GUI中却不那么重要。

        3
  •  4
  •   Bram    9 年前

    可以将文本呈现为三角形面,并避免使用纹理。 这样可以避免在缩放文本时取消锐化边缘。 我编写了一个低聚合ASCII字体,它是开放源代码的,可在 my github .

    另一种在文本上使用锐边的方法是 SDF font rendering 但这也受到了一些人工制品的影响。

        5
  •  1
  •   fa.    14 年前

    每四字符处理一个显示列表(仅在文本更改时更新)对于大多数情况来说已经足够了。

    我用它来处理x11字体,使用xloadQueryFont、glgenlists、glxusesFont、glcallists 您有一组描述每个字符的显示列表。

    glcallLists函数接受文本的char*参数,它可以嵌入显示列表中。

    所以最后只需要一次调用来显示块文本。

    G.Pakosz建议的字体纹理类似,但您可以计算自己的“按字符”显示列表。

    第一个选项将非常慢,因为它需要在每次文本更改时基于处理器的呈现。

        6
  •  1
  •   Ned Bingham    14 年前

    可以只使用这两个功能:

    void renderstring2d(char string[], float r, float g, float b, float x, float y)
    {
        glColor3f(r, g, b);
    
        glRasterPos2f(x, y);
        for(unsigned int i = 0; i &lt strlen(string); i++)
            glutBitmapCharacter(GLUT_BITMAP_9_BY_15, string[i]);
    }
    
    void renderstring3d(char string[], float r, float g, float b, float x, float y, float z)
    {
        glDisable(GL_LIGHTING);
        glColor3f(r, g, b);
    
        glRasterPos3f(x, y, z);
        for(unsigned int i = 0; i &lt strlen(string); i++)
            glutBitmapCharacter(GLUT_BITMAP_9_BY_15, string[i]);
    }

    然后在渲染二维文本时,不要忘记重置模型视图和投影矩阵。

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    
    // Render text and quads
    
    glPopMatrix();
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();

    不需要使用这些函数渲染到四元体,因为这些函数直接渲染到帧缓冲区。

    如果这对你不起作用的话,看看这个。 http://www.opengl.org/resources/faq/technical/fonts.htm

    它讨论了如何使用glbitmap、gldrawpixels和alpha混合来呈现文本。

        7
  •  1
  •   rombust    11 年前

    这是很难做到的,特别是如果你想使用亚像素字体渲染技术。看看 ClanLib SDK . 它使用批处理渲染器在单个OpenGL调用中渲染整个文本屏幕。因为它有一个基于zlib的许可证,如果您不想使用sdk本身,就可以提取它的代码。