Как сделать OpenGL live text-rendering для GUI?
я реализую графический интерфейс, построенный поверх OpenGL. Я пришел к проблеме, что каждый GUI будет иметь-рендеринг текста. Я знаю несколько методов рендеринга текста в OpenGL, однако мне интересно, какой из них лучше всего подходит для GUI.
обычно в GUI у нас есть два типа текста-статический и живой. Статика достаточно проста - мы можем отобразить TTF в текстуру и забыть об этом. Это" живой " текст, который больше беспокоит меня-представьте себе консоль или чат в многопользовательская игра.
Я подумал о нескольких вариантах:
- нет особых случаев -- рендеринг и загрузка текстуры каждый раз, когда текст изменяется, имея в виду только для повторной передачи его, когда на самом деле появляется новый текст, и пытается разделить больший текст на мелкие части (например, на строку чата). Однако это все равно оставит нас висеть в случаях, таких как строка оценки, которая меняется все время, или вводный текст, который отображает " на символ "(стиль пишущей машинки, наблюдаемый в некоторых научно-фантастических игры)
- quad-per character -- это также кажется популярным решением, вы готовите текстуру с таблицей ASCII и визуализируете текстурированный символ quad. Однако у меня есть серьезные сомнения в эффективности такого решения. Советы, как сделать это быстрее, также будут приветствоваться. гибридные решения-я понятия не имею, как реализовать это чисто
следовательно, вопрос в том, как отобразить текст в OpenGL эффективно?
Если это поможет, я кодирую в STL / Boost-heavy C++ и нацелен на графические карты GForce 6 и более поздних версий.
7 ответов
EDIT2: Шон Барретт только что вышел растровые шрифты для C / C++ 3D программистов.
EDIT: еще один драгоценный камень кода, который стоит посмотреть, это Font Stash, который использует stb_truetype.h.
можно создать текстуру, в которой отображаются все символы шрифта. Затем вы просто рисуете текстурированные квадроциклы с ортогональной проекцией и правильными текстурными координатами: этот подход работает, когда ваш текст находится в язык, который не содержит много символов: например, английский. Текстура шрифта создается один раз в начале приложения, а затем рендеринг квадроциклов происходит очень быстро.
Это то, что я использую, и я считаю, что это самый быстрый способ рендеринга текста в OpenGL. Сначала я использовал генератор растровых шрифтов Angelcode инструмент, а затем я интегрировал FreeType непосредственно и построил большую текстуру, содержащую все глифы при запуске приложения. Что касается советов по улучшению скорость рендеринга квадроциклов, я просто использовал VBO как для остальной геометрии в моем приложении.
Я удивлен, что у вас есть сомнения по поводу рендеринга quad, в то время как вы, похоже, не беспокоитесь о производительности генерации текстуры на cpu, затем ее загрузки, а затем привязки к ней, чтобы, наконец, отобразить прямоугольник с ним, что для каждого кадра. Изменение состояний OpenGL является узким местом, а не 500-1000 квадроциклов, которые вы будете использовать для текста.
кроме того, посмотрите на библиотеки, такие как FTGL библиотека, которая преобразует весь шрифт в полигоны (геометрические шрифты).
попробуйте прочитать это:http://dmedia.dprogramming.com/?n=Tutorials.TextRendering1.
описанный подход является типичным методом рендеринга текста с графическими API. Один символ на квадроцикл и все данные изображения для текста в одной текстуре. Если вы можете поместить весь набор символов в одну текстуру (на самом деле, в зависимости от размера текстуры, вы можете поместить несколько), рендеринг очень быстрый.
ключ что привязка текстуры-это операция, которую нужно минимизировать. Если вы можете отобразить весь текст с одной текстурой, не имеет значения, сколько текста вам нужно поместить на экран. Даже если вам нужно переключать текстуры несколько раз (разные шрифты, разные атрибуты шрифта [жирный, подчеркивание и т. д.]), производительность все равно должна быть хорошей. Производительность текста может быть более критичной для HUD, но менее важной в GUI.
вы можете отображать текст как триангулированные грани и избегать использования текстуры. Таким образом, вы избегаете нерезких краев при увеличении текста. Я написал низкий Поли ASCII шрифт, который является открытым исходным кодом и доступен в мой github.
другой способ иметь острые края на вашем тексте -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
можно просто использовать эти две функции:
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-текст, не забудьте сбросить матрицы modelview и projection.
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
// Render text and quads
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
вам не нужно визуализировать в quad, используя эти функции, потому что эти функции визуализируются непосредственно в framebuffer.
и если это не сработает для вас, проверьте это. http://www.opengl.org/resources/faq/technical/fonts.htm
Он говорит о рендеринге текст с использованием glBitmap, glDrawPixels и альфа-смешивания.
Это сложно сделать, особенно если вы хотите использовать субпиксельного рендеринга шрифтов методов. Взгляните на ClanLib SDK для. Он использует пакетный рендеринг для отображения всего экрана текста в одном вызове OpenGL. Поскольку он имеет лицензию на основе zlib, вы можете извлечь его код, если вы не хотите использовать сам SDK
на четырех символов обрабатывается мысль список отображения (обновляется только при изменении текста) вполне достаточно для большинства случаев.
Я использовал его с шрифтами X11, используя XLoadQueryFont, glGenLists, glXUseXFont, glCallLists у вас есть массив отображаемых списков, описывающих каждый символ.
функция glCallLists принимает аргумент char * для текста и может быть встроена в список отображения.
таким образом, вы получаете один вызов для отображения блоков текст.
текстура шрифта, предложенная G. Pakosz, аналогична, но вы вычисляете свои собственные списки отображения "по символу".
ваши первые параметры будут довольно медленнее, так как это потребует рендеринга на основе процессора при каждом изменении текста.