OpenGLでの文字列の描画(ビットマップフォント版)

以下のソースコード(ysglusefontbitmap.c, ysglfontdata.c, ysglfontdata.h)を使うと、OpenGLの弱点のひとつである、文字の描画が各プラットフォームごとにばらばらであるという問題を一応解決できます。もう少し具体的には、

  • wglUseFontBitmapやglXUseXFontを、YsGlUseFontBitmap?x?関数で置き換えることで、プラットフォームごとに違うコードを書かなくてもいい。とくに、フォントを生成する部分で、わけのわからないパラメータに悩まなくていい。(何ポイントとかつべこべ言わずにピクセル数の指定がしたいんじゃ!と、叫ばなくていい)
  • Windowsでは、フォントのベースラインをRaster Positionに合わせるのに対して、Linux (GLX)ではフォントの左下角をRaster Positionに合わせるため、同じ位置にフォントを描画させてもWindowsとLinuxのバイナリで微妙に位置がずれる。しかも、Windows版で、フォントのベースラインが下から何ピクセルの位置か知る方法が無い。が、YsGlUseFontBitmap?x?を使ってフォントのディスプレイリストを作ると、この問題は無い。

というメリットがあります。6x7, 6x8, 8x8, 8x12, 12x16, 16x20, 16x24, 20x28, 20x32ピクセルのフォントが使えます。

なお、ここでダウンロードできるファイル、ysglfontdata.h, ysglfontdata.c, ysglusefontbitmap.c の3本は、それを使用した結果の責任を使用者が負う(=作者は責任を負わない)という一点だけ同意していただければ、作者に断らなくても、フリーでも商用でも、オープンソースでもプロプライエタリでも、プログラムに組み込んで使っていただいて構いません。僕は、本当の意味のオープンソースってのはこういうことだと思ってます。紐をつけるとか、ソースコードの開示を義務付けるとか、そんなのはぜんぜんオープンじゃありません。

ただ、難点としては、僕はあまり芸術的なセンスが無いので、字体は綺麗ではありません。あと、プロポーショナルフォントも作ろうと思えば作れますが、僕がOpenGLで文字を描画するときというのは、字が縦横にそろって欲しいことがほとんどなので、今のところ固定長フォントしか作ってません。

[ソースファイルダウンロード]

[GLAUXを使った例題]

[GLXを使った例題]

[Cocoa (MacOSX) を使った例題]

使い方については例題を見るのが一番早いと思います。コンパイル方法は、例題の先頭のコメントに書いてあります。一応Cのソースにしましたが、#ifdef __cplusplusしてあるので、C++でもそのまま使えます。

OpenGLは、3次元グラフィックスを描画させたら、極めて強力なAPIです。今だと、ほとんどのGPUのハードウェアによるサポートがあり、OpenGLでかなり高速に3Dアニメーションが実現できるようになりました。ほんの10年も前は、PCでOpenGLなんて、絵は出るけどとても動くレベルではなかったんですけどね。

そんな強力なOpenGLですが、字を描かせると途端に弱くなります。せっかくOpenGLはWindows、Linux、MacOS X、さらにはiPhoneにまで共通のコードの利用ができるのに、字を描くとこだけ各プラットフォームごとに別のコードを書かなくてはなりません。そんなもんだから、出てくる字がプラットフォームごとに微妙に違ってみたり、位置が合わなかったり、プログラムを移植しようとするといろいろ問題が出ます。文字の描画が標準化されていないというのがOpenGLの数少ない欠点のひとつでした。

ただ、だったら自力で文字を表示する関数を作ってしまえば、プラットフォーム依存の問題は解決できるので、OpenGLの関数glDrawPixelsを使ってやってみようと思ったのですが、そのときは、二点の問題が出て実現できませんでした。ひとつは、glDrawPixelsだとビットマップを描画してから、指定のピクセル数Raster Positionを移動することができないので、位置の計算はCPU側で担当せざるえを得なくて、ディスプレイリスト化できなかった点。もうひとつは、色の指定ができなかった点。

が、しばらく前、OpenGLの別の関数の仕様を確認したくてOpenGLのリファレンスを見ていたら、glBitmapなる関数が目に留まりました。ん?なにこれ?OpenGLってglDrawPixelsの他にもう一個ビットマップ描画の関数があるの?と、思って中身を見てみたら、納得。glBitmap関数は、ビットマップを描画してからRaster Positionを指定のピクセル数分移動することができることがわかりました。もう、かれこれ15年近くOpenGLを使ってますが、ぜんぜん気づきませんでした。(これを知ってれば過去に文字の描画で苦労したのがどれほど楽だったことか。。。。)要するに、wglUseFontBitmapやglXUseXFont関数は、内部でglBitmapをディスプレイリストに登録していただけということがわかりました。

そういうわけで、仕組みがわかったので、調子に乗って作ったのが、↑のプログラムです。多分、ざっと検索した感じでは、同じような問題で困っている人が他にもいるかと思ったので、公開することにしました。

更新履歴

2009/09/20 公開

2009/09/21 MacOS X上でも使えるように、ヘッダのIncludeのパスを修正。(MACOSXマクロを定義しておくと、"OpenGL/gl.h"を見に行くようにした。) [このバージョンをダウンロード]

2010/08/15 フォントを改善。多分前よりかなり読みやすくなった。6x10と7x10フォントを追加。

例題の実行画面