Как сделать OpenGL живой рендеринг текста для графического интерфейса? - PullRequest
40 голосов
/ 15 января 2010

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

Обычно в графическом интерфейсе у нас есть два типа текста - статический и живой. Статика достаточно проста - мы можем визуализировать TTF для текстуры и забыть об этом. Меня больше беспокоит «живой» текст - представьте себе консоль или чат в многопользовательской игре.

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

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

Поэтому возникает вопрос - как эффективно визуализировать текст в OpenGL?

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

Ответы [ 7 ]

30 голосов
/ 15 января 2010

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

РЕДАКТИРОВАТЬ: еще один драгоценный камень кода, который стоит посмотреть - Шрифтов * * * * * * * * * * * * * * * * * * * * * * * * * * * * .


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

Это то, что я использую, и я считаю, что это самый быстрый способ визуализации текста в OpenGL. Сначала я использовал

Генератор растровых шрифтов Angelcode , а затем непосредственно интегрировал FreeType и создал большую текстуру, содержащую все глифы при запуске приложения. Что касается советов по улучшению скорости рендеринга четырехугольников, я просто использовал VBO для остальной части геометрии в моем приложении.

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

Также обратите внимание на библиотеки, такие как FTGL , которые преобразуют весь шрифт в полигоны (геометрические шрифты).

9 голосов
/ 15 января 2010

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

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

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

5 голосов
/ 07 марта 2015

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

Еще один способ иметь острые края на вашем тексте - это Отрисовка шрифта SDF , но это страдает некоторыми артефактами.

4 голосов
1 голос
/ 25 сентября 2013

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

1 голос
/ 15 января 2010

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

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-текст, не забудьте сбросить матрицы вида и проекции.

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

1 голос
/ 15 января 2010

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

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

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

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

Текстура шрифта, предложенная Дж. Пакошем, похожа, но вы вычисляете свои собственные списки отображения «по символам».

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

...