Подтвердить что ты не робот

Как нарисовать текст, используя только методы OpenGL?

У меня нет параметров для использования, кроме методов opengl (это методы glxxx()()). Мне нужно нарисовать текст, используя только методы gl. Прочитав красную книгу, я понимаю, что это возможно только через метод glBitmap(). Если это единственный возможный способ, то может ли кто-нибудь помочь мне с информацией о массиве пикселей для всех символов. Есть ли другой способ рисования текста?

4b9b3361

Ответ 1

Теория

Почему это сложно

Популярные форматы шрифтов, такие как TrueType и OpenType, представляют собой векторные контурные форматы: они используют кривые Безье для определения границы буквы.

esujR.gif

Источник изображения.

Преобразование этих форматов в массивы пикселей (растеризация) слишком специфично и выходит за рамки OpenGL, особенно потому, что OpenGl не имеет нечетких примитивов (например, см. Почему нет круга или эллипс-примитив в OpenGL?

Самый простой способ - сначала создать растровые шрифты на CPU, а затем передать массив пикселей в OpenGL как текстуру.

OpenGL знает, как хорошо справляться с массивами пикселей через текстуры.

Атлас текстуры

Мы можем растрировать символы для каждого фрейма и повторно создавать текстуры, но это не очень эффективно, особенно если символы имеют фиксированный размер.

Более эффективный подход состоит в том, чтобы растрировать все персонажи, которые вы планируете использовать, и набивать их на одной текстуре.

И затем перенесите это на GPU один раз и используйте текстуру с пользовательскими координатами uv, чтобы выбрать правильный символ.

Этот подход называется https://en.wikipedia.org/wiki/Texture_atlas, и его можно использовать не только для текстур, но и для других повторно используемых текстур, таких как плитки в 2D-игра или веб-пользовательский интерфейс.

Википедия: картина полной текстуры, которая сама взята из freetype-gl, хорошо иллюстрирует это:

9k6jy.png

Я подозреваю, что оптимизация размещения символов для наименьшей проблемы текстуры - проблема NP-hard, см. Какой алгоритм можно использовать для упаковки прямоугольников разного размера в самый маленький прямоугольник, который возможен в довольно оптимальный способ?

Тот же метод используется в веб-разработке для передачи нескольких небольших изображений (например, значков) сразу, но там он называется "CSS Sprites": https://css-tricks.com/css-sprites/ и используются, чтобы скрыть латентность сети, а не связь между CPU/GPU.

Растровые методы без процессора

Существуют также методы, которые не используют растровый процессор для текстур.

Растрирование процессора просто, потому что он использует GPU как можно меньше, но мы также начинаем думать, можно ли еще больше использовать эффективность GPU.

Этот видеоролик FOSDEM 2014 https://youtu.be/LZis03DXWjE?t=886 объясняет другие существующие методы:

Шрифты внутри 3D-геометрии с перспективой

Рендеринг шрифтов внутри 3D-геометрии с перспективой (по сравнению с ортогональным HUD) намного сложнее, потому что перспектива может сделать одну часть персонажа намного ближе к экрану и больше, чем другую, делая равномерную дискретизацию процессора ( например растра, тесселяция) выглядят плохо на закрытой части. Это фактически активная тема исследования:

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

Поле расстояний является одним из популярных методов.

Реализация

Следующие примеры были протестированы на Ubuntu 15.10.

Поскольку это сложная проблема, как обсуждалось ранее, большинство примеров являются большими и будут взорвать предел 30k char этого ответа, поэтому просто клонируйте соответствующие репозитории Git для компиляции.

Однако все они полностью открыты, поэтому вы можете просто RTFS.

Решения FreeType

FreeTypeвыглядит как доминирующая библиотека растеризации шрифтов с открытым исходным кодом, поэтому она позволит нам использовать шрифты TrueType и OpenType, что делает его самым элегантным решением.

Примеры/учебники:

Другие растеризаторы шрифтов

Те кажутся менее хорошими, чем FreeType, но могут быть более легкими:

Антон OpenGL 4 Учебник пример 26 "Растровые шрифты"

Шрифт был создан автором вручную и сохранен в одном файле .png. Буквы хранятся в форме массива внутри изображения.

Этот метод, конечно, не очень общий, и у вас возникнут трудности с интернационализацией.

Построить с помощью:

make -f Makefile.linux64

Предварительный просмотр вывода:

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

opengl-tutorial глава 11 "2D-шрифты"

Текстуры генерируются из файлов DDS.

В учебном пособии объясняется, как были созданы файлы DDS, используя CBFG и Paint.Net.

Предварительный просмотр вывода:

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

По какой-то причине Suzanne отсутствует для меня, но счетчик времени отлично работает: https://github.com/opengl-tutorials/ogl/issues/15

FreeGLUT

GLUT имеет glutStrokeCharacter, а FreeGLUT - с открытым исходным кодом... https://github.com/dcnieho/FreeGLUT/blob/FG_3_0_0/src/fg_font.c#L255

OpenGLText

https://github.com/tlorach/OpenGLText

Растровое изображение TrueType. Сотрудник NVIDIA. Цели для повторного использования. Еще не пробовал.

Пример ARM Mali GLES SDK

http://malideveloper.arm.com/resources/sample-code/simple-text-rendering/, кажется, кодирует все символы в PNG и сокращает их оттуда.

SDL_ttf

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

Источник: https://github.com/cirosantilli/cpp-cheat/blob/d36527fe4977bb9ef4b885b1ec92bd0cd3444a98/sdl/ttf.c

Живет в отдельном дереве SDL и легко интегрируется.

Не обеспечивает реализацию текстурного атласа, поэтому производительность будет ограничена: Эффективно рендеринг шрифтов и текста с помощью SDL2

Связанные темы

Ответ 2

enter image description here

Используйте glutStrokeCharacter(GLUT_STROKE_ROMAN, myCharString).

Пример: ПРОСМОТР ЗВЕЗДНЫХ ВОЙН.

#include <windows.h>
#include <string.h>
#include <GL\glut.h>
#include <iostream.h>
#include <fstream.h>

GLfloat UpwardsScrollVelocity = -10.0;
float view=20.0;

char quote[6][80];
int numberOfQuotes=0,i;

//*********************************************
//*  glutIdleFunc(timeTick);                  *
//*********************************************

void timeTick(void)
{
    if (UpwardsScrollVelocity< -600)
        view-=0.000011;
    if(view < 0) {view=20; UpwardsScrollVelocity = -10.0;}
    //  exit(0);
    UpwardsScrollVelocity -= 0.015;
  glutPostRedisplay();

}


//*********************************************
//* printToConsoleWindow()                *
//*********************************************

void printToConsoleWindow()
{
    int l,lenghOfQuote, i;

    for(  l=0;l<numberOfQuotes;l++)
    {
        lenghOfQuote = (int)strlen(quote[l]);

        for (i = 0; i < lenghOfQuote; i++)
        {
          //cout<<quote[l][i];
        }
          //out<<endl;
    }

}

//*********************************************
//* RenderToDisplay()                       *
//*********************************************

void RenderToDisplay()
{
    int l,lenghOfQuote, i;

    glTranslatef(0.0, -100, UpwardsScrollVelocity);
    glRotatef(-20, 1.0, 0.0, 0.0);
    glScalef(0.1, 0.1, 0.1);



    for(  l=0;l<numberOfQuotes;l++)
    {
        lenghOfQuote = (int)strlen(quote[l]);
        glPushMatrix();
        glTranslatef(-(lenghOfQuote*37), -(l*200), 0.0);
        for (i = 0; i < lenghOfQuote; i++)
        {
            glColor3f((UpwardsScrollVelocity/10)+300+(l*10),(UpwardsScrollVelocity/10)+300+(l*10),0.0);
            glutStrokeCharacter(GLUT_STROKE_ROMAN, quote[l][i]);
        }
        glPopMatrix();
    }

}
//*********************************************
//* glutDisplayFunc(myDisplayFunction);       *
//*********************************************

void myDisplayFunction(void)
{
  glClear(GL_COLOR_BUFFER_BIT);
  glLoadIdentity();
  gluLookAt(0.0, 30.0, 100.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
  RenderToDisplay();
  glutSwapBuffers();
}
//*********************************************
//* glutReshapeFunc(reshape);               *
//*********************************************

void reshape(int w, int h)
{
  glViewport(0, 0, w, h);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(60, 1.0, 1.0, 3200);
  glMatrixMode(GL_MODELVIEW);
}

//*********************************************
//* int main()                                *
//*********************************************


int main()
{
    strcpy(quote[0],"Luke, I am your father!.");
    strcpy(quote[1],"Obi-Wan has taught you well. ");
    strcpy(quote[2],"The force is strong with this one. ");
    strcpy(quote[3],"Alert all commands. Calculate every possible destination along their last known trajectory. ");
    strcpy(quote[4],"The force is with you, young Skywalker, but you are not a Jedi yet.");
    numberOfQuotes=5;

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(800, 400);
    glutCreateWindow("StarWars scroller");
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glLineWidth(3);

    glutDisplayFunc(myDisplayFunction);
    glutReshapeFunc(reshape);
    glutIdleFunc(timeTick);
    glutMainLoop();

    return 0;
}

Ответ 3

Рисование текста в простом OpenGL не является задачей с перенапряжением. Вероятно, вы должны взглянуть на библиотеки для этого (либо с помощью библиотеки, либо в качестве примера реализации).

Хорошими отправными точками могут быть GLFont, OpenGL Font Survey и Учебник NeHe для растровых шрифтов (Windows).

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

Ответ 4

В этой статье описывается, как визуализировать текст в OpenGL, используя различные методы.

При использовании opengl существует несколько способов:

  • с помощью glBitmap
  • с использованием текстур
  • с использованием списков отображения

Ответ 5

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

Не нужно использовать Glut или любое другое расширение, просто базовую работоспособность OpenGL. Он выполняет свою работу, не говоря уже о том, что это было сделано в течение десятилетий профессиональными программистами в очень успешных играх и других приложениях.

Ответ 6

Я думаю, что лучшим решением для рисования текста в OpenGL являются текстурные шрифты, я работаю с ними в течение длительного времени. Они гибкие, быстрые и приятные (с некоторыми задними исключениями). Я использую специальную программу для преобразования файлов шрифтов (например,.ttf) в текстуру, которая сохраняется в файле некоторого внутреннего формата шрифта (я разработал формат и программу на основе http://content.gpwiki.org/index.php/OpenGL:Tutorials:Font_System, хотя моя версия прошла довольно далеко от оригинала, поддерживающего Unicode и т.д.). При запуске основного приложения шрифты загружаются из этого "внутреннего" формата. Посмотрите ссылку выше для получения дополнительной информации.

При таком подходе основное приложение не использует никаких специальных библиотек, таких как FreeType, что нежелательно и для меня. Текст рисуется с использованием стандартных функций OpenGL.