Как сделать рендеринг текста в OpenGL для графического интерфейса?

Я реализую GUI, созданный поверх OpenGL. Я столкнулся с проблемой, что каждый GUI будет иметь - рендеринг текста. Я знаю несколько методов рендеринга текста в OpenGL, однако мне интересно, какой из них лучше всего подходит для графического интерфейса.

Как правило, в графическом интерфейсе мы имеем два типа текста - статические и живые. Static достаточно прост - мы можем сделать TTF текстурой и забыть об этом. Это "живой" текст, который больше беспокоит меня - воображайте консоль или живой чат в многопользовательской игре.

Я подумал о нескольких вариантах:

  • никаких особых случаев - визуализировать и загружать текстуру каждый раз, когда текст изменяется, имея в виду только перезаписать его, когда на самом деле появляется новый текст, и пытаться разделить большой текст на мелкие части (например, на линию чата). Однако это все равно оставит нас висящими в таких случаях, как линия оценки, которая меняется все время, или вводный текст, который отображает "на символ" (стиль пишущей машинки, видимый в некоторых научно-фантастических играх).
  • quad-per character - это также кажется популярным решением, вы готовите текстуру с таблицей ASCII и визуализируете текстурированный четырехсимвольный символ. Однако у меня есть серьезные сомнения в эффективности такого решения. Советы о том, как сделать это быстрее, также приветствуются.
  • гибридные решения - однако я понятия не имею, как реализовать это чисто

Вопрос заключается в том, как эффективно обрабатывать текст в OpenGL?

Если это помогает, я кодирую STL/Boost-heavy С++ и нацеливаюсь на графические карты GForce 6 и более поздние версии.

Ответ 1

EDIT2: Шон Барретт только что выпустил Растровые шрифты для программистов на C/С++ 3D.

EDIT: еще один драгоценный камень кода, который стоит посмотреть Font Stash, который использует Sean Barrett stb_truetype.h.


Вы можете создать текстуру, в которой вы будете отображать все символы шрифта. Затем вы просто рисуете текстурированные квадрациклы с орфографической проекцией и правильными координатами текстуры: этот подход работает, когда ваш текст находится на языке, который не содержит много символов: например, английский. Текстура шрифта создается один раз в начале приложения, а затем рендеринг выполняется четким образом.

Это то, что я использую, и я считаю, что это самый быстрый способ визуализации текста в OpenGL. Сначала я использовал инструмент Angelcode Bitmap Font Generator, а затем интегрировал FreeType непосредственно и построил большую текстуру, содержащую все глифы при запуске приложения. Что касается подсказок для улучшения скорости рендеринга четности, я просто использовал VBO, как и для остальной геометрии в моем приложении.

Я удивлен, что у вас есть сомнения по поводу рендеринга кварков, в то время как вы, похоже, не беспокоитесь о производительности генерации текстуры на процессоре, затем загружаете его, а затем привязываете его, чтобы в итоге сделать прямоугольник с ним, что для каждого Рамка. Изменение состояний OpenGL является узким местом, а не 500 - 1000 квадрациклов, которые вы будете использовать для текста.

Также обратите внимание на библиотеки, такие как библиотека

Ответ 2

Попробуйте прочитать это: http://dmedia.dprogramming.com/?n=Tutorials.TextRendering1.

Описанный подход является типичным методом для текстового рендеринга с графическими API. Один символ на квадрат и все данные изображения для текста в одной текстуре. Если вы можете поместить весь свой набор символов в одну текстуру (на самом деле, в зависимости от размера текстуры, возможно, вы сможете поместить несколько) рендеринг выполняется очень быстро.

Ключ состоит в том, что привязка текстуры - это операция, которую необходимо минимизировать. Если вы можете отобразить весь текст с помощью одной текстуры, не имеет значения, сколько текста вам нужно разместить на экране. Даже если вам нужно переключать текстуры несколько раз (разные шрифты, разные атрибуты шрифта [жирный, подчеркивающий и т.д.]), Производительность все равно будет хорошей. Эффективность текста может быть более важной для HUD, но это менее важно в графическом интерфейсе.

Ответ 3

Вы можете отобразить текст в виде триангулированных граней и избегать использования текстуры. Таким образом, вы избегаете нерезких краев при увеличении текста. Я создал шрифт с низким поли ASCII, который открыт с открытым исходным кодом и доступен в my github.

Другой способ иметь острую ребра на вашем тексте рендеринг шрифтов SDF, но это страдает некоторыми артефактами.

Ответ 4

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

https://github.com/urho3d/Urho3D/blob/6b63f20065558cff1842bc8e1e3c6ee11f4bf577/Source/Samples/26_ConsoleInput/ConsoleInput.cpp

введите описание изображения здесь

Ответ 5

может просто использовать эти две функции:

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]);
}

то при рендеринге 2D-текста не забудьте reset как матрицу просмотра, так и проекцию.

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 и альфа-смешивания.

Ответ 6

Это сложно сделать, особенно если вы хотите использовать методы субпиксельной визуализации шрифтов. Посмотрите ClanLib SDK. Он использует пакетный рендеринг для визуализации всего экрана текста в одном вызове OpenGL. Поскольку у него есть лицензия на основе zlib, вы можете извлечь ее код, если вы не хотите использовать сам SDK

Ответ 7

В каждом обработанном четырехзначном символе список отображения (обновленный только при изменении текста) вполне достаточно для большинства случаев.

Я использовал его с шрифтами X11, используя XLoadQueryFont, glGenLists, glXUseXFont, glCallLists у вас есть массив списков отображения, описывающих каждый символ.

Функция glCallLists принимает аргумент char * для вашего текста и может быть встроена в список отображения.

Итак, вы получаете один вызов для отображения текста блоков.

Текстура шрифта, предложенная Г. Пакошем, аналогична, но вы вычисляете свои собственные списки отображения "по символу".

Ваши первые параметры будут довольно медленными, так как для каждого изменения текста потребуется рендеринг на основе процессора.