日本語文字列を描画するには

解説

OpenGLで、日本語文字列を描画する関数は、今のところ標準では用意されていないので、自作します。

OpenGLで、日本語文字列を描画するための一つの方法は、
① WindowsAPIを用いて、日本語フォントオブジェクトを作成する。
② ①で作成した日本語フォントオブジェクトと、WindowsAPIを用いて、日本語文字列のOpenGL用の白黒ビットマップを作成する。
③ ②で作成した日本語文字列のOpenGL用の白黒ビットマップと、Openglの関数を用いて、日本語文字列を描画する。
です。

再描画のたびに、毎回①②③を処理するのは効率的ではありません。
(フォントが変わらないのであれば、2回目以降の描画時には、①の処理は1回目の処理の結果を再利用する方が効率的です。
 フォントも文字列も変わらないのであれば、2回目以降の描画時には、①②③の処理は1回目の処理の結果を再利用する方が効率的です。)
①②③の処理を一つのクラスにまとめ、さらに①②③の処理の結果を再利用する仕組みを持ったクラスを作成します。




実装例

「① WindowsAPIを用いて、日本語フォントオブジェクトを作成する。」関数の用意

フォントの名前、フォントの大きさ、をインプットに、フォントオブジェクトを作成し、そのハンドルをアウトプットする関数
HFONT CreateJFont( HDC hDC, const TCHAR* const pszFontName, float fFontSize )
を用意します。

LOGFONT の lfHeight パラメータは、MSDNヘルプのLOGFONTのページを参考に、フォントサイズからフォントの高さが計算されるようにします。
LOGFONT の lfCharSet パラメータは、日本語キャラクタセットである SHIFTJIS_CHASET にします。

「② ①で作成した日本語フォントオブジェクトと、WindowsAPIを用いて、日本語文字列のOpenGL用の白黒ビットマップを作成する。」関数の用意

フォントオブジェクトのハンドル、日本語文字列、をインプットに、日本語文字列のOpenGL用の白黒ビットマップと、ビットマップのサイズ(幅とサイズ)をアウトプットする関数
GLubyte* CreateStringMonoBits( HDC hDC, HFONT hFont, const TCHAR* const pszString, SIZE& rsizeBitmap )
を用意します。
CreateStringMonoBits の内部の処理関数も用意します。

日本語文字列の幅と高さを計算(GetTextExtentPoint32関数)し、
この幅と高さを元に、Windows用のビットマップを作成(CreateBitmapIndirect関数)し、
メモリデバイスコンテキスト上のWindows用のビットマップに日本語文字列を出力(TextOut関数)し、
Windows用のビットマップを元にOpenGL用のビットマップ(GLubyte配列)を作成(CreateMonoBits関数)
するようにします。

「③ ②で作成した日本語文字列のOpenGL用の白黒ビットマップと、Openglの関数を用いて、日本語文字列を描画する。」手続き

「③ ②で作成した日本語文字列のOpenGL用の白黒ビットマップと、Openglの関数を用いて、日本語文字列を描画する。」手続きは、

  1. glColor関数呼び出しで文字色を指定する。
  2. glRasterPos関数呼び出しでモデル座標系における描画位置(ラスターポジション)を指定する。
  3. glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );を呼び出す。
  4. ②で作成した日本語文字列のOpenGL用の白黒ビットマップを引数にして、glBitmap関数を呼び出す。

上記手続きにより、日本語文字列の文字以外の部分は透明、文字部分は指定した色、で描画されます。

「OpenGLで日本語文字列を描画する」クラスの作成

①②③の処理を一つのクラスにまとめ、さらに①②③の結果を再利用する仕組みを持ったクラスを作成します。
クラス宣言の内容は以下です。(クラス定義は OGLJText.cpp を参照)



このクラスを使用すると、

  1. フォントの名前、フォントの大きさ、文字列ビットマップの基点の位置(glRasterPosで指定した座標値に、文字列ビットマップの4隅のどこをあわせるか)を指定して、「OpenGLで日本語文字列を描画する」クラスオブジェクトを生成する。
  2. Format関数呼び出しで、描画する文字列を指定する。
  3. glColor関数呼び出しで、文字色を指定する。glRasterPos関数呼び出しで、描画位置(ラスターポジション)を指定する。
  4. Render関数呼び出しで、文字列を描画する。

という手続きで、日本語文字列を描画することができます。
①②③の処理の結果の再利用は、クラス使用者からは隠蔽されます。
(フォントも文字列も変わらないのであれば、2回目以降の描画時には、ディスプレイリスト化されたものを呼び出すので、①②③の処理は行われません。
 フォントが変わらず、文字列だけが変わるのであれば、2回目以降の描画時には、フォントオブジェクトは再利用されるので、フォントオブジェクトの作成処理は行われません。)
(「文字色の指定(③-1)」「描画位置の指定(③-2)」は、このクラスの仕事ではないという仕様です。)

OGLJText.lzh(OGLJText.cpp, OGLJText.h)

「OpenGLで日本語文字列を描画する」クラスの利用例

作成した「OpenGLで日本語文字列を描画する」クラスを、モデルビューワを作る(OpenGL+MFC) (Visual C++ 2005版) のプログラムに、組み込んでみます。

「OpenGLで日本語文字列を描画する」クラスを組み込む前の、モデルビューワソースファイル
ModelViewerOpenGLMFC2005_16_src.lzh

プロジェクトを開く

ModelViewerOpenGLMFC2005_16_src.lzh を解凍し、モデルビューワプロジェクトを開きます。

「OpenGLで日本語文字列を描画する」クラスファイルをプロジェクトに追加

OGLJText.cpp
OGLJText.h
をモデルビューワプロジェクトフォルダにコピーします。

「メニュー/プロジェクト/既存項目の追加」を選択します。
OGLJText.cpp
OGLJText.h
を追加します。

ピックOpenGLビュークラスのメンバ変数の宣言の編集

OpenGLPickView.h に
#include "OGLJText.h"
を追加します。
OpenGLPickView.h のピックOpenGLビュークラス定義にCOGLJTextクラスオブジェクトメンバ変数(3つの軸の先端テキストと、1つの描画速度テキスト)の宣言を追加します。

ピックOpenGLビュークラスのコンストラクタ、デストラクタの編集

OpenGLPickView.h のピックOpenGLビュークラスのコンストラクタ、デストラクタに、COGLJTextクラスオブジェクトメンバ変数の初期化処理および終了処理を追加します。

RenderSceneの編集

を反映させ、OpenGLPickView.cpp の COpenGLPickView::RenderScene関数 の内容を以下のようにします。



ビルドし、エラー、警告がないことを確認します。

実行

起動直後


3つの軸の先端テキストは、トラッキング(マウス操作による描画領域の回転、拡大縮小、平行移動)操作に追従し、描画位置が変わります。
描画速度テキストは、トラッキングにより、描画速度値の文字列が変わりますが、描画位置は変わりません。

ダウンロード

「OpenGLで日本語文字列を描画する」クラスを組み込み後の、モデルビューワソースファイル
ModelViewerOpenGLMFC2005_16_OGLJText_src.lzh