LINUX.ORG.RU

Текст в OpenGL


0

1

Всем доброго времени суток.

Столкнулся с проблемой вывода текста в OpenGL. Нашёл огромное множество способов решения. Из-за незнания всей глубины некоторых из них, не знаю какой выбрать.

Пробовал выводить текст через текстуру 16Х16 символов, заранее нарисованную. ФПС высокий выдаёт, но текст при изменении размеров оставляет желать лучшего.

Выводил через SDL_Font, фпс упал аж в 2 раза. Так и должно быть или у меня руки кривые?=)

Попробывал через библиотеку FreeType. Тоже Фпс падает. Ещё проблема с кириллицей и разноширинными буквами.

Моя задача в общем заключается в создании поля ввода/вывода текста, поэтому страшно использовать библиотеки с ttf шрифтами (боюсь тормозов и проблем вывода кириллицы), в тоже время не очень хочется работать с текстурными шрифтами, т.к. не очень гибкое и красивое решение.

Посоветуйте в каком направлении работать: ttf или просто текстуру рисовать?

Ответ на: комментарий от Babikov

использовал как раз когда нужна была кириллица

shty ★★★★★
()
Ответ на: комментарий от Babikov

Не могу собрать FTGL под винду mingw. Выдаёт ошибку при ./configure: GL library could not be found, please specifity its location with..

Babikov
() автор топика
Ответ на: комментарий от shty

Спасибо вам снова. У меня такое мнение появилось: по ходу FTGL юзает FreeType. Получается, что FTGL просто упрощает работу с FreeType?

Babikov
() автор топика
Ответ на: комментарий от Babikov

У меня такое мнение появилось: по ходу FTGL юзает FreeType. Получается, что FTGL просто упрощает работу с FreeType?

ЕМНИП используется FreeType2, но по сути всё верно, по крайней мере с точки зрения вывода текста

shty ★★★★★
()

Если поля ввода/вывода не должны жить в изображаемом мире, а должны отображаться на экране как обычно, то есть если к ним не надо применять преобразования координат, и есть доступ к окну на достаточно низком уровне, то можно попробовать любую библиотеку рендеринга текста. Например, я делал обычное иксовое окно и в нём рисовал через GLX, а поверх рендерил текст с помощью Xft. Правда, насчёт скорости работы ничего в данном случае не могу сказать --- дальше простейших вещей я там не продвинулся. Но думаю, что должно быть быстрее FTGL хотя бы за счёт экономии на преобразовании координат.

anonymous
()

Понятно что есть 2 метода отображения текста: через текстуру или «3д». Если надо отображать текст одного шрифта, без всяких примочек, то лучше использовать тектуры. В противном случае, для увеличения быстродействия (когда символы прорисовывается как 3д объекты) - можно загнать вершины в буфера видюшной оперативки. Ну или на край использовать листы, но они после опенЖЛ 3.1 признаны устаревшими, их лучше не использовать.

rip86oz
()
Ответ на: комментарий от shty

Возникла проблема с установкой FTGL по данной ссылке:

Step Four

Next, in ftgl-*/, find config.h. Open it in your favorite editor and comment out line 47 (#define HAVE_STRNDUP 1). Also check the other defines to make sure the FTGL library won't look for any non-existent header files when compiling (simply comment out the #define line that relates to that file). Then, copy it to src/, src/FTGlyph/, src/FTLayout/, and src/FTFont/..

Я не могу найти этот самый config.h. Там есть другие конфиги, только они по другому называются и в них нет 47 строки с #define HAVE_STRNDUP 1. Где этот config.h. Без него не моги скомпилить ftgl.

Babikov
() автор топика
Ответ на: комментарий от Babikov

Возникла проблема с установкой FTGL по данной ссылке:

Step Four

Next, in ftgl-*/, find config.h. Open it in your favorite editor and comment out line 47 (#define HAVE_STRNDUP 1). Also check the other defines to make sure the FTGL library won't look for any non-existent header files when compiling (simply comment out the #define line that relates to that file). Then, copy it to src/, src/FTGlyph/, src/FTLayout/, and src/FTFont/..

Я не могу найти этот самый config.h. Там есть другие конфиги, только они по другому называются и в них нет 47 строки с #define HAVE_STRNDUP 1. Где этот config.h. Без него не моги скомпилить ftgl.

к сожалению, так подробно я уже не помню

shty ★★★★★
()

У себя использую freetype2, который динамически генерирует текстуру с запрошенными глифами, если таковых еще не сгенерено.

Недостатком будут некоторые тормоза в первый момент времени генерации текстуры с глифами. Но и это обходится достаточно легко - кеш текстуры на диске и предварительная прегенерация основных глифов.

Зато из плюсов - любой символ, доступный в ttf, высокая скорость рендеринга строки в которой редко появляются еще не сгенеренные глифы.

Реализация, конечно, несколько сложнее, но за пару часов вполне возможно написать такое в первом приближении.

Выводил через SDL_Font, фпс упал аж в 2 раза.


Если мне память не изменяет, то SDL_Font возвращает сурфейс с отрендеренным текстом. И делать это каждый кадр несколько расточительно :)

andreyu ★★★★★
()
Ответ на: комментарий от Babikov

> Понятно, спасибо. Я понял, чтобы с русскими буквами в FreeType работать надо использовать wchar_t?

Ну юникод, он и в России юникод.

andreyu ★★★★★
()
Ответ на: комментарий от andreyu

Научился работать с русскими буквами в FreeType. Теперь столкнулся с другой проблемой: если текста мало, то всё просто летает, при большем количестве падает ФПС.
Читал на GameDev, что для ускорения надо все глифы загонять в одну текстуру. Попробовал, результат примерно тот же, что и при хранении отдельной текстуры для каждого символа.
Интересует как можно ускорить отображение текста в неком подобие Edit, который позволяет текст непросто отображать, но и вводить.

Babikov
() автор топика
Ответ на: комментарий от andreyu

Я не загоняю каждый кадр глиф. Один раз это делаю. Просто получается, что надо рисовать много квадов с текстурами символов. Как можно ускорить этот процесс? Спасибо.

Babikov
() автор топика
Ответ на: комментарий от Babikov

> Просто получается, что надо рисовать много квадов с текстурами символов. Как можно ускорить этот процесс? Спасибо.

А как обычно вы рисуете много квадов или трианглов?

andreyu ★★★★★
()
Ответ на: комментарий от Babikov

VBO для квада? ;-) И какой смысл держать квады вообще? Нужен один квад, который будет прорисовываться с разными текстурами... надеюсь у тебя для каждой буквы отдельный квад не создаётся?

Не знаю от чего будут тормоза вообще - у меня с шейдерами(глянец+диффузия - на одновременно 30 источников света) не было тормозов при прорисовке квадов (16*16) замостивших экран (1280*1024) + сложная многополигональная геометрия.

Видимо где-то вызывается тормозящая всё функция.

rip86oz
()

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

vertexua ★★★★★
()
Ответ на: комментарий от rip86oz

> Нужен один квад, который будет прорисовываться с разными текстурами...

Один квад? И для вывода каждого символа менять текстуру и/или делать отдельный вызов glDraw*()? Хороший пример того, как делать НЕ надо... Все стараются геометрию в батчи объединять, изворачиваться по всякому для минимизации количества смен стейтов и вызовов glDraw*(), а тут по буковке за раз выводить...

надеюсь у тебя для каждой буквы отдельный квад не создаётся?

Генерить кучу квадов для всех символов в пределах одной текстуры со шрифтом, совать их в один буфер и выводить всё разом. 99.9% текста каждый кадр менять нет необходимости, т.ч. и перегенерировать буфер нужно не так часто. Статический или [очень] редко меняющийся текст вообще можно в VBO загнать. Для остального терпимо будет и обычный буфер — ((2–3 координаты на вершину + 2 текстурные координаты) * 4 вершины в кваде) * 4 байта в float = 16–20 байт на вершину, а т.к. часто меняющегося текста обычно немного, то шина не помрёт (можно и в VBO затолкать, но потеряется профит в лёгкости изменения длины текста ибо регулярно пересоздавать OpenGL-ные вершинные и индексные буферы нифига не круто).

anonymous
()
Ответ на: комментарий от anonymous

Текстуру биндить надо не больше раз чем кол-во различных символов... или такой алгоритм анонимусам не представляется? ...и VBO менять таки придётся часто, т.к. ВВОД теста.

rip86oz
()
Ответ на: комментарий от rip86oz

> такой алгоритм анонимусам не представляется?

Представляется. Поэтому я и написал «менять текстуру и/ИЛИ делать отдельный вызов», а не «менять текстуру и делать отдельный вызов». И это не отменяет унылости твоего возмущения по поводу «по кваду на каждый символ» и предложения делать всего 1 квад, который двигать перед выводом каждого нового символа. Предлагаешь, например, для текста в 1000 символов делать 1000 трансформаций и 1000 раз вызывать glDraw*()? Это бред и так никто в здравом уме делать не будет, если только не хочет устроить «праздник» GPU и драйверу видеокарты.

...и VBO менять таки придётся часто, т.к. ВВОД теста.

Вершинные и индексные буферы в системной памяти уже отменили? Они больше не поддерживаются и предлагается для добавления каждого символа пересоздавать весь VBO? Частое удаление-создание-заполнение VBO в видеопамяти вполне может оказаться тормознее realloc-а буферов в «обычной» памяти и песылка данных по шине.

anonymous
()
Ответ на: комментарий от anonymous

От 1000 трансформаций будут проблемы?...)

Ну и я посмортю что будет, когда из середины или начала буфера придётся выразать «удалённые» символы... А потом всё сдвигать... и сдвигать... символы конечно. Или буфер перекраивать. Я уж не знаю какой способ там выбрать))

Если нужна супер производителдьность, то можно попробоать использовать glDrawArraysInstanced + шейдеры. И за один вызов прорисуется весь текст - но имхо уже перебор для данной задачи:-\

rip86oz
()
Ответ на: комментарий от rip86oz

> От 1000 трансформаций будут проблемы?...)

Для текста это слишком неэффективно — 1000 пересылок в GPU трансформаций и команд на прорисовку займёт больше времени, чем этот GPU будет выводить твои квады. Ты пойми, рисовать батчами по 2 треугольника — это ппц, на который идут только любители приключений. Хуже, разве что, устаревший режим OpenGL с glBegin/glEnd, glVertex3f и т.п..

Ну и я посмортю что будет, когда из середины или начала буфера придётся выразать «удалённые» символы... А потом всё сдвигать... и сдвигать... символы конечно. Или буфер перекраивать.

Ну, символы в буфере строки всё равно придётся «сдвигать... и сдвигать...». Т.ч. и перестроить вершинные-индексные буферы труда не составит, тем более, что делать это каждый кадр может и не понадобиться. Можно и поднапрячься, сделав «перекраивание» только изменённой части буфера (например, вставили/удалили кусок текста в середине строки, так вместо полной перестройки буферов неизменённое начало строки оставить, а переделать только сдвинувшуюся вторую часть). Даже для твоего упоротого варианта с двиганием единственного квада тебе придётся делать практически то же самое, т.к. всё равно придётся считать и грузить матрицы, пересчитывать текстурные координаты и т.д. (часть работы можно переложить на шейдеры, но напрягать CPU всё равно придётся, только оверхед на кучу вызовов glDraw*() никуда не денется).

Если нужна супер производителдьность, то можно попробоать использовать glDrawArraysInstanced + шейдеры.

Количество констант в шейдерах совсем не бесконечно и для не слишком короткого текста их может попросту не хватить. А передавать данные в шейдер придётся, т.к. случаи, когда шейдеру для вывода кучи объектов достаточно одного только instance ID, слишком редки и текст к ним не относится.

anonymous
()
Ответ на: комментарий от anonymous

х_х

Лучше разговоро окончить. Аноним меня убил.)))

ТС сам решит, как делать, и в лучшем случае сравнит производительность способов.

rip86oz
()
Ответ на: комментарий от rip86oz

> Лучше разговоро окончить.

Согласен. Потроллили друг друга и хватит. Дальше ТС пусть сам разбирается. :)

anonymous
()
Ответ на: комментарий от anonymous

Спасибо за такие подробные ответы.

Babikov
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.