如何做一个GUI的OpenGL生活文字渲染?
我正在实现一个基于OpenGL的GUI。 我遇到了每个GUI都会有文本呈现的问题。 我知道在OpenGL中渲染文本的几种方法,但是,我不知道它们中哪一个最适合于GUI。
通常在一个GUI中,我们有两种types的文本 – 静态和现场。 静态很容易 – 我们可以渲染一个TTF到一个纹理,并忘记它。 这是“活”的文本,更困扰我 – 想象控制台,或在多人游戏中的实时聊天。
我想到了几个select:
- 没有特殊的情况 – 每次文本改变时渲染和加载纹理,记住只有在实际出现新文本时重新渲染纹理,并尝试将较大的文本分割成小部分(如每个聊天行)。 然而,这仍然会让我们挂在像是一直在变化的分数线的情况下,或者是一个呈现“每个人物”的简介文本(在一些科幻游戏中看到的打字机风格)
- 四个字符 – 这似乎也是一个stream行的解决scheme,你准备一个纹理与ASCII表格,并呈现一个纹理四字符。 但是,我对这种解决scheme的效率深表怀疑。 提示如何更快地做到这一点也是值得欢迎的。
- 混合解决scheme – 但我不知道如何实现这个干净
因此,问题是如何有效地在OpenGL中呈现文本?
如果这有帮助,我编写STL / Boost-heavy C ++,针对GForce 6及更高版本的graphics卡。
EDIT2:Sean Barrett刚刚为C / C ++ 3D程序员发布了位图字体 。
编辑:另一个值得一看的代码gem是利用肖恩·巴雷特的stb_truetype.h的 字体 存储 。
您可以创build一个纹理,在其中渲染字体的所有字符。 然后,您只需绘制具有正投影和适当的纹理坐标的纹理四边形:当文本使用的语言不包含太多符号时,此方法可以工作:如英语。 字体纹理在应用程序的开始处创build一次,然后渲染四边形非常快。
这就是我正在使用的,我相信这是在OpenGL中渲染文本的最快方法。 起初,我使用了Angelcode的位图字体生成器工具,然后我直接集成了FreeType ,并在应用程序启动时构build了一个包含所有字形的大纹理。 至于提高四边形渲染速度的技巧,我只是在我的应用程序中使用了VBO。
我很惊讶你对四画面渲染有怀疑,而你似乎不担心在CPU上产生纹理的性能,然后上传它,然后绑定它,最终渲染一个矩形,每个帧。 改变OpenGL的状态是瓶颈,而不是500 – 1000的文本。
另外,看看像FTGL库那样将整个字体转换成多边形(几何字体)的库。
尝试读这个: http : //dmedia.dprogramming.com/?n=Tutorials.TextRendering1 。
所描述的方法是使用graphicsAPI进行文本呈现的典型方法。 每个四边形一个字符,以及单个纹理中的所有文本图像数据。 如果你可以把你的整个字符集合到一个纹理中(实际上,取决于纹理的大小,你可能可以适应几个纹理),渲染速度非常快。
关键是纹理绑定是您需要最小化的操作。 如果您可以使用单个纹理渲染所有文本,则无论您需要在屏幕上放置多less文本都无关紧要。 即使你不得不多次切换纹理(不同的字体,不同的字体属性(粗体,下划线等)),性能应该还是不错的。 对于HUD,文本性能可能更为重要,但在GUI中则不太重要。
您可以将文本渲染为三angular形的面,并避免使用纹理。 这样,您可以避免文字放大时出现不清晰的边缘。 我创作了一个低聚ASCII字体,这个字体是开源的,可以在我的github上find 。
另一种在文本上有锐利边缘的方法是SDF字体渲染 ,但是这会受到一些人工制品的影响。
freetype-gl https://github.com/rougier/freetype-gl是一个集成了freetype和OpenGL的库。;
想象控制台
请参阅控制台: https : //github.com/rougier/freetype-gl/blob/a4cfb9abac19a0ab62b625a9b6f856e032fe3732/demos/console.c
如何让它在Ubuntu 15.10上运行: https : //github.com/rougier/freetype-gl/issues/82#issuecomment-216025527
更多细节: 如何使用OpenGL方法绘制文本?
Urho3D ConsoleInput.cpp
可以只使用这两个function:
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 < 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 < strlen(string); i++) glutBitmapCharacter(GLUT_BITMAP_9_BY_15, string[i]); }
那么当您渲染2D文本时,不要忘记重置模型视图和投影matrix。
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混合呈现文本。
这很难做,特别是如果你想使用亚像素字体渲染技术。 看看ClanLib SDK 。 它使用批渲染器在单个OpenGL调用中渲染整个文本屏幕。 由于它具有基于zlib的许可证,因此如果您不希望使用SDK本身,则可以提取其代码
每个处理四字符的人认为显示列表(仅当文本改变时才更新)对于大多数情况来说已经足够了。
我用X11字体使用XLoadQueryFont,glGenLists,glXUseXFont,glCallLists你有一个显示列表数组描述每个字符。
glCallLists函数为您的文本接受一个char *参数,并且它可以被embedded在显示列表中。
所以你最终只需要一个调用来显示块文本。
G.Pakoszbuild议的字体纹理是相似的,但是你计算自己的“按字符”显示列表。
您的第一个选项将会非常慢,因为在每次文本更改时都需要基于处理器的渲染。