OpenGLにはフォント描画命令が無いので、テクスチャに文字を描き、そのテクスチャをポリゴンに貼って描画することで、文字列の描画を実現します。

テクスチャに直接文字を書くことはできないので、CPU側に確保したメモリ領域に文字を描画し、そのメモリ領域をVRAMに転送することで、テクスチャに文字を書きます。

メモリ領域に文字を書くには、NSString*のdrawInRectを使います。メモリ領域からテクスチャへの転送には、glTexImage2Dを使います。

ただし、テクスチャを毎回glTexImage2Dで新規確保すると重いので、最初に一度だけglTexImage2Dでテクスチャを確保して、以降はglTexSubImage2Dで転送だけを行います。

以降の説明では、以下の構造体を使っています。


//確保したテクスチャを格納
struct DynamicTextureStruct{
GLuint id;
int width;
int height;
int original_width;
int original_height;
};

//文字列の描画先のメモリを格納
struct FontTextureMipmap{
struct DynamicTextureStruct texture; //テクスチャ情報構造体
CGContextRef _context; //コンテキスト
GLubyte* data; //テクスチャのRGBA実データ
};

//文字列描画用のフォント
UIFont *m_font; //文字の描画に使うフォント


データの流れは次のようになります。


初期化
(1)文字列描画用のメモリ領域を確保してglTexImage2Dでテクスチャを確保
(2)GLubyte* dataへの文字列描画コンテキストCGContextRef _contextとフォントUIFont *m_fontを確保
ゲームループ
(3)NSString*のdrawInRectでGLubyte* dataに文字を描画
(4)glTexSubImage2Dでテクスチャに転送


(1)VRAMにテクスチャを生成します。


//テクスチャサイズを定義する
int s=FONT_TEXTURE_MIPMAP_SIZE[i];
m_p_font_texture->texture.width=s;
m_p_font_texture->texture.height=s;

// テクスチャを作成する
glGenTextures(1, &(m_p_font_texture->texture.id));

// テクスチャをバインドする
glBindTexture(GL_TEXTURE_2D, m_p_font_texture->texture.id);

// テクスチャの設定を行う
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);

//テクスチャのRGBAデータの配列を確保する
m_p_font_texture->data = (GLubyte *)malloc(m_p_font_texture->texture.width * m_p_font_texture->texture.height * 4);

//テクスチャデータをVRAM上に転送し領域を確保する
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_p_font_texture->texture.width,m_p_font_texture->texture.height,0, GL_BGRA, GL_UNSIGNED_BYTE, m_p_font_texture->data);


(2)文字描画用のコンテキストを確保します


//文字描画用のコンテキストを作成する
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
m_p_font_texture->_context = CGBitmapContextCreate(m_p_font_texture->data, m_p_font_texture->texture.width, m_p_font_texture->texture.height, 8, m_p_font_texture->texture.width * 4, colorSpace, kCGImageAlphaPremultipliedLast);

//フォントを確保する
m_font = [UIFont systemFontOfSize:14];


(3)文字列を描画します


//実際の描画サイズを取得
CGSize size=[text sizeWithFont:m_font constrainedToSize:CGSizeMake(sx,512) lineBreakMode:UILineBreakModeWordWrap];
m_p_font_texture->texture.original_width=size.width;
m_p_font_texture->texture.original_height=size.height;

//文字画像は上下反転しているので描画時にUV反転する
//また、クリッピングエリアも反転するので注意

// 文字を描画する
memset(m_p_font_texture->data,0,m_p_font_texture->texture.width*m_p_font_texture->texture.height*4);
UIGraphicsPushContext(m_p_font_texture->_context);
UIColor *color=[UIColor colorWithRed:r/255.0f green:g/255.0f blue: b/255.0f alpha:1.0f];
[color set];
[text drawInRect:CGRectMake(0,m_p_font_texture->texture.height-m_p_font_texture->texture.original_height,sx,m_p_font_texture->texture.original_height) withFont:m_font lineBreakMode:UILineBreakModeWordWrap alignment:UITextAlignmentLeft];
UIGraphicsPopContext();


(4)文字をテクスチャに転送します


// テクスチャをバインドする
glBindTexture(GL_TEXTURE_2D, m_p_font_texture->texture.id);

// テクスチャを更新する
glTexSubImage2D(GL_TEXTURE_2D, 0, 0,m_p_font_texture->texture.height-m_p_font_texture->texture.original_height, m_p_font_texture->texture.width,m_p_font_texture->texture.original_height, GL_RGBA, GL_UNSIGNED_BYTE, m_p_font_texture->data);
}


後はこのテクスチャを描画すればOKです。

尚、glTexSubImage2Dで転送する画像の横幅は、最初に確保したテクスチャ領域の横幅になります。CPU->VRAMへの転送は結構遅いので、複数のサイズの文字描画用テクスチャを用意しておいて、文字サイズに応じて使うテクスチャを切り替えるとよいかと思います。

----------------------------------------
2011/4/19追記
続編がiPhoneのOpenGLで文字を書く場合の高速化法にあります。

また、ソースコードを
http://www.abars.biz/blog/FontTexture.h
http://www.abars.biz/blog/FontTexture.mm
に置きましたのでどうぞ。