Нарисуйте текст в OpenGL ES - PullRequest
       76

Нарисуйте текст в OpenGL ES

121 голосов
/ 27 августа 2009

В настоящее время я разрабатываю небольшую игру OpenGL для платформы Android, и мне интересно, есть ли простой способ визуализации текста поверх отрисованного фрейма (например, HUD с оценкой игрока и т. Д.). В тексте также потребуется использовать собственный шрифт.

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

Есть идеи?

Ответы [ 12 ]

162 голосов
/ 02 декабря 2010

Рендеринг текста в текстуру проще, чем в демонстрационном примере Sprite Text. Основная идея - использовать класс Canvas для рендеринга в растровое изображение, а затем передать растровое изображение в текстуру OpenGL:

// Create an empty, mutable bitmap
Bitmap bitmap = Bitmap.createBitmap(256, 256, Bitmap.Config.ARGB_4444);
// get a canvas to paint over the bitmap
Canvas canvas = new Canvas(bitmap);
bitmap.eraseColor(0);

// get a background image from resources
// note the image format must match the bitmap format
Drawable background = context.getResources().getDrawable(R.drawable.background);
background.setBounds(0, 0, 256, 256);
background.draw(canvas); // draw the background to our bitmap

// Draw the text
Paint textPaint = new Paint();
textPaint.setTextSize(32);
textPaint.setAntiAlias(true);
textPaint.setARGB(0xff, 0x00, 0x00, 0x00);
// draw the text centered
canvas.drawText("Hello World", 16,112, textPaint);

//Generate one texture pointer...
gl.glGenTextures(1, textures, 0);
//...and bind it to our array
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);

//Create Nearest Filtered Texture
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

//Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);

//Use the Android GLUtils to specify a two-dimensional texture image from our bitmap
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

//Clean up
bitmap.recycle();
100 голосов
/ 27 августа 2009

В Android SDK нет простого способа рисования текста в представлениях OpenGL. Оставляя вас со следующими опциями.

  1. Поместите TextView поверх SurfaceView. Это медленно и плохо, но самый прямой подход.
  2. Рендеринг общих строк в текстуры и просто рисование этих текстур. Это, безусловно, самый простой и быстрый, но наименее гибкий.
  3. Свернуть свой код рендеринга текста на основе спрайта. Вероятно, второй лучший вариант, если 2 не вариант. Хороший способ намочить ноги, но имейте в виду, что, хотя это кажется простым (и базовые функции), оно становится все сложнее и сложнее по мере добавления новых функций (выравнивание текстур, работа с переносами строк, шрифты переменной ширины и т. Д.). ) - если вы выберете этот маршрут, сделайте его максимально простым!
  4. Используйте готовую библиотеку с открытым исходным кодом. Есть несколько людей, которые охотятся в Google, их сложно интегрировать и запустить. Но, по крайней мере, как только вы это сделаете, вы получите всю гибкость и зрелость, которые они обеспечивают.
35 голосов
/ 25 мая 2012

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

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

В учебник входит полный код, который можно использовать в любом проекте:)

8 голосов
/ 09 марта 2011

По этой ссылке:

http://code.neenbedankt.com/how-to-render-an-android-view-to-a-bitmap

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

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

7 голосов
/ 19 февраля 2011

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

CBFG - http://www.codehead.co.uk/cbfg

Android загрузчик - http://www.codehead.co.uk/cbfg/TexFont.java

6 голосов
/ 27 августа 2009

Я посмотрел на пример текста со спрайтом, и он выглядит ужасно сложным для такой задачи, я тоже рассматривал рендеринг на текстуру, но меня беспокоит возможное снижение производительности. Я мог бы просто пойти с представлением вместо этого и беспокоиться о портировании, когда пришло время пересечь этот мост:)

4 голосов
/ 27 августа 2009

Посмотрите на образец "Sprite Text" в GLSurfaceView samples .

3 голосов
/ 18 января 2013

ИМХО, есть три причины использовать OpenGL ES в игре:

  1. Избегайте различий между мобильными платформами, используя открытый стандарт;
  2. Чтобы иметь больше контроля над процессом рендеринга;
  3. Чтобы получить выгоду от параллельной обработки на GPU;

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

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

Лучший способ - выделить удаленные буферы (объекты буфера вершин - VBO) для вершин и текстур в начале кода, избегая ленивых операций передачи памяти во время рисования.

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

Итак, мое решение простое:

  1. Создание текстуры для общих меток и предупреждений;
  2. Создание текстуры для чисел 0-9, ":", "+" и "-". Одна текстура для каждого персонажа;
  3. Создание удаленных VBO для всех позиций на экране. Я могу визуализировать статический или динамический текст в этих позициях, но VBO статические;
  4. Создайте только один текстурный VBO, так как текст всегда отображается в одну сторону;
  5. Во время прорисовки я рендеринг статического текста;
  6. Для динамического текста я могу заглянуть в позицию VBO, получить текстуру персонажа и нарисовать ее, символ за раз.

Операции рисования выполняются быстро, если вы используете удаленные статические буферы.

Я создаю XML-файл с позициями экрана (в зависимости от процента диагонали экрана) и текстурами (статические и символы), а затем загружаю этот XML перед рендерингом.

Чтобы получить высокую скорость FPS, вам следует избегать генерации VBO во время розыгрыша.

3 голосов
/ 09 июля 2012

Взгляните на CBFG и порт Android загрузки / рендеринга код. Вы должны быть в состоянии вставить код в свой проект и использовать его сразу.

  1. CBFG

  2. Загрузчик Android

У меня проблемы с этой реализацией. Он отображает только один символ, когда я пытаюсь изменить размер растрового изображения шрифта (мне нужны специальные буквы), полное рисование завершается неудачно: (

3 голосов
/ 27 августа 2009

Если вы настаиваете на использовании GL, вы можете отобразить текст на текстуре. Предполагая, что большая часть HUD является относительно статичной, вам не нужно загружать текстуры в текстурную память слишком часто.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...