是否有适合iPhone SDK的OpenGL文本绘图库?

时间:2009-02-04 17:00:49

标签: cocoa-touch opengl-es freetype

我想弄清楚在OpenGL中绘制一些文本的简单方法。我的研究表明它是一项相当复杂的任务。它涉及创建(或在运行时生成)字体图集纹理,然后为每个字母创建一个四边形,只有正确的位置和纹理坐标。

我听说过一些关于freetype的好东西,但是对于如何让它在iPhone上运行却发现很少,而且看起来相当复杂。

那么是否有任何Objective-C包装的OpenGL文本库可以与人们一直使用的iPhone SDK一起使用?或者我只是在思考这个问题,而且我想要一个更容易的方法?

8 个答案:

答案 0 :(得分:22)

实现此目的的一种方法是设置UILabel,然后将其图层渲染为纹理。对此的间接途径是首先使用文本,字体等设置UILabel,然后使用以下代码

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

将UILabel捕获到UIImage。然后,您可以在CrashLanding项目中使用Texture2D类的initWithImage:构造函数将其转换为纹理。

它看起来像initWithImage:在该示例中,将UIImage重新呈现为位图上下文并使用它来创建纹理。通过一些工作,您可以从该方法中提取相关代码并更改上面的代码,直接将图层渲染到纹理中。

这样,在为纹理创建文本时,您可以获得UILabel的Unicode和字体支持。

答案 1 :(得分:8)

使用freetype创建纹理图集以及所有字形信息的描述正是我在当前iPhone项目中所做的。

我在预处理步骤中完成所有字体的解析(在Windows上的所有C#中都是如此)。地图集本身生成并且仅包含所需的字符 - 为了减少空间,我有时最终生成的不仅仅是单个图集以保持纹理大小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文档,它基本上为您提供了字形数据而没有搞乱,它只是将其从字体中拉出来。至于纹理本身,你得到freetype来渲染每个字形,然后管理它来构建纹理。这个我作为一个完全独立于我的主应用程序的预处理。

以下是我的工具代码的摘录:http://pastebin.com/md1c6354

请注意,这只是为了我的眼睛,而不是为了公众消费,所以原谅它是如此混乱的事实:)

答案 2 :(得分:6)

我找到了一个简单的解决方案。这是我为它写的一个快速功能。 (您将需要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 :(得分:3)

谢谢你的方法。它节省了我一些时间。

虽然有一些我不得不改变的事情。 glBlendFunc调用需要:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_ALPHA)

其次,文本似乎只是一个点。 CGRectMake调用正在创建一个1x1矩形,除非我读错了。

答案 4 :(得分:3)

使用“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);

简单:)

它带有unicode支持,“按需”加载字形,甚至可以输出变量

font.print(x, y, z) << "fps: " << fps;

答案 5 :(得分:2)

我创建了一个类似于“musings”字体库的Font类,减去了内存泄漏,减去了每个字符,每帧的纹理创建。尽管如此,它仍然为每个角色使用不同的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

答案 6 :(得分:1)

检查崩溃着陆演示。提供的Texture2D类允许使用文本和字体创建纹理。 (希望有一个更好的答案我会喜欢一种简单的方法来绘制一个opengles视图)

答案 7 :(得分:1)

是的,我知道有2个。诀窍是,你必须使用Quartz(CGContext *函数)渲染到纹理,然后渲染该纹理以供用户查看。

如果您担心性能,还可以使用Quartz生成纹理图集。

制作纹理生成工具(在xCode中)once you know the basics of rendering a font相当容易。

您所要做的就是拥有一个有效的CGContext。您可以在texture loader中找到一些非常棒的示例代码。

基本上代码是:

// 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字体列表为available hereprerenders here

相关问题