Есть ли приличная библиотека для рисования текста OpenGL для iPhone SDK? - PullRequest
24 голосов
/ 04 февраля 2009

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

Я слышал кое-что хорошее о freetype, но очень мало узнал о том, как запустить его на iPhone, и он кажется довольно сложным.

Так есть ли какая-нибудь Objective-C упакованная текстовая библиотека OpenGL, которая работает с iPhone SDK, который используют люди? Или я просто слишком обдумываю это, и я упускаю более простой подход?

Ответы [ 8 ]

22 голосов
/ 04 февраля 2009

Один из способов сделать это - настроить UILabel, а затем преобразовать его слой в текстуру. Косвенным путем к этому будет сначала настроить UILabel с текстом, шрифтом и т. Д., А затем использовать следующий код

UIGraphicsBeginImageContext(yourLabel.frame.size);
[yourLabel.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *layerImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

чтобы захватить UILabel для UIImage. Затем вы можете использовать initWithImage: конструктор класса Texture2D в проекте CrashLanding, чтобы преобразовать его в текстуру.

Это похоже на initWithImage: в этом примере повторно визуализирует UIImage в растровом контексте и использует его для создания текстуры. Немного поработав, вы можете извлечь соответствующий код из этого метода и изменить приведенный выше код, чтобы сделать слой непосредственно в текстуре.

Таким образом, вы получаете замечательную поддержку UILabel для Unicode и шрифтов при создании текста для вашей текстуры.

8 голосов
/ 04 февраля 2009

Ваше описание использования freetype для создания атласа текстуры вместе со всей информацией о глифе - это именно то, что я делаю в моем текущем проекте iPhone.

Я делаю весь анализ шрифта на этапе предварительной обработки (все в C # в Windows, как это происходит). Сам атлас генерируется и содержит только необходимые символы - чтобы сократить пространство, я также иногда заканчиваю тем, что генерирую больше чем один атлас, чтобы сохранить размеры текстур pow2 и разумного разрешения.

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

Для чего это стоит, вот как я определяю символ глифа внутри моего маленького движка:

struct FontGlyph
{

u32 char_code;

u32 m_x;                // base x position on tpage

u32 m_y;            // base y position on tpage

u32 m_width;            // glyph width

u32 m_height;           // glyph height

i32 m_horiBearingX;     // Distance to X shift

i32 m_horiBearingY;     // Distance to Y shift

u32 m_horiAdvance;      // Total Horizontal advance this character requires

u32 m__tpage_index;     // Which tpage does this glyph use?

};

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

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

Не стесняйтесь отвечать или комментировать, если вам нужны какие-либо другие детали. (И удачи:)


Ответьте на ваш комментарий, когда мне не хватило места в разделе комментариев ...

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

Вот отрывок моего кода инструмента, который делает это: http://pastebin.com/md1c6354

Обратите внимание, хотя, это когда-либо было предназначено только для моих глаз, а не для общественного потребления, так что извините за то, что это чертовски грязно:)

6 голосов
/ 24 марта 2009

Я нашел простое решение для этого. Вот быстрая функция, которую я написал для нее. (Вам понадобится класс Texture2D.)

- (void) drawText:(NSString*)theString AtX:(float)X Y:(float)Y {
// Use black
glColor4f(0, 0, 0, 1.0);

// Set up texture
Texture2D* statusTexture = [[Texture2D alloc] initWithString:theString dimensions:CGSizeMake(150, 150) alignment:UITextAlignmentLeft fontName:@"Helvetica" fontSize:11];

// Bind texture
glBindTexture(GL_TEXTURE_2D, [statusTexture name]);

// Enable modes needed for drawing
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

// Draw
[statusTexture drawInRect:CGRectMake(X,Y-1,1,1)];   

// Disable modes so they don't interfere with other parts of the program
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);    
}

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

3 голосов
/ 21 января 2010

Используйте библиотеку шрифтов "musings":

http://www.themusingsofalostprogrammer.com/2010/01/how-to-do-font-rendering-in-opengl-on.html

Font font("Verdena");
font.print("Hello World!", x, y, z);

Легко:)

Он поставляется с поддержкой юникода, загружает глифы «по требованию» и даже имеет способ вывода переменных

font.print(x, y, z) << "fps: " << fps;
3 голосов
/ 28 марта 2009

Спасибо за этот метод. Это сэкономило мне время.

Была пара вещей, которые мне пришлось изменить, хотя. Вызов glBlendFunc должен быть:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_ALPHA)

А во-вторых, текст, казалось, рисует в одной точке. Вызов CGRectMake создает прямоугольник 1x1, если я не читаю это неправильно.

2 голосов
/ 10 декабря 2012

Я создал класс Font, похожий на библиотеку шрифтов musings, за исключением утечек памяти и минус создание текстуры для каждого персонажа, каждого кадра. Тем не менее, он по-прежнему использует разные glTexture для каждого персонажа. Примечание: Texture2D был изменен, чтобы закомментировать удаление текстуры.

init в конструкторе: _font = new Font("Helvetica", 40);

использовать в методе redraw (): _font->draw("Hello, World!", 50, 100, ALIGN_LEFT);

Ссылка на GitHub:

https://github.com/chandl34/public/tree/master/personal/c%2B%2B/Font

1 голос
/ 22 сентября 2012

Да, есть 2, о которых я знаю . Хитрость в том, что вы должны визуализировать текстуру с помощью Quartz (функции CGContext *), а затем визуализировать эту текстуру для просмотра пользователем.

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

Довольно просто запустить инструмент генерации текстур (в xCode) , если вы знаете основы рендеринга шрифта .

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

В основном код выглядит так:

// Create the cgcontext as shown by links above

// Now to render text into the cg context,
// the drop the raw data behind the cgcontext
// to opengl.  2 ways to do this:
// 1)  CG* way: (advantage: easy to use color)
CGContextSelectFont(cgContext, "Arial", 24, kCGEncodingMacRoman);

// set color to yellow text
CGContextSetRGBFillColor(cgContext, 1, 1, 0, 1) ; // Be sure to use FILL not stroke!

// draw it in there
CGContextShowTextAtPoint(cgContext, 20, 20, "HI THERE", strlen("HI THERE") ) ;

/*
// WAY #2:  this way it's always black and white
// DRAW SOME TEXT IN IT
// that works ok but let's try cg to control color
UIGraphicsPushContext(cgContext);
UIFont *helv = [UIFont fontWithName:@"Helvetica" size:[UIFont systemFontSize]];
NSString* msg = @"Hi hello" ;  
[msg drawInRect:CGRectMake(0,0,pow2Width,pow2Height) withFont:helv] ;
    UIGraphicsPopContext();
*/

// put imData into OpenGL's memory
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pow2Width, pow2Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imData);
CHECK_GL ;

Выглядит неплохо и сглаженно,

tex atlas

Список шрифтов ios доступен здесь , а с prerenders здесь

1 голос
/ 04 февраля 2009

Проверьте демонстрацию аварийной посадки. Предоставленный класс Texture2D позволяет создавать текстуры с текстом и шрифтом. (Надеюсь, будет лучший ответ, я бы хотел использовать более простой способ рисования в виде открытых окон)

...