読者です 読者をやめる 読者になる 読者になる

OpenGLをC++11でラップしてみんとてするなり 第2回

OpenGL C++

 OpenGLの機能を全てラップしたライブラリをブログ上で開発する気など毛頭ありませんので、OpenGLC++11の紹介となるようなサンプルを幾つか作っていこうと思います。
 今のところ、以下の4つの機能を実装していこうかと思いますが、他にも面白そうなネタが見つかれば、後々紹介しようかと思っています。

●glEnable()/glDisable()/glIsEnabled()

 まずは単純に、GPUの特定機能をON/OFFするだけのこれらの関数をラップします。
 何が単純かというと、これらを使う際には、操作対象を変更する関数を呼ぶ必要がないためで、設計は次のようになるでしょう。

  • コンストラクタ:フラグの現在状態を取得する
  • メソッド:フラグを書き換えたり、現在状態を取得したりする
  • コピー/代入:不可(フラグの値の代入ならばOK)
  • デストラクタ:フラグを最初の状態に戻す

●行列スタック操作

 こちらはglEnable()等よりは少々複雑になり、「どの行列スタックを操作するか」という指定も入ってきます。
 操作対象の行列スタックを間違えてしまうと表示が崩れますので、これは何としても避けたいところです。

  • コンストラクタ:指定の行列スタックの現在状態を取得する
  • メソッド:指定の行列スタックに対して操作を行う、現在値を取得する
  • コピー/代入:不可(行列値の代入ならばOK)
  • デストラクタ:指定の行列スタックを最初の状態に戻す

●テクスチャ操作

 テクスチャを扱う際は、操作対象を指定するだけでなく、操作対象を作成/破棄する必要もでてきます。
 作成/破棄はコンストラクタ/デストラクタで容易に実装できるとして、問題はコピー処理です。
 通常は、コピーをした際にはコピー元と同じ状態の新規テクスチャを作成したいところです。が、関数の戻り値としてテクスチャ・オブジェクトを返す時などには、テクスチャIDだけコピーだけできれば十分ですし、そうしなければパフォーマンスが悪くなります。
 ここはC++11から導入されたムーブ・セマンティクスを活用して、パフォーマンスを確保しましょう。

  • コンストラクタ:新しいテクスチャIDを作成する
  • ムーブコンストラクタ:移動元のテクスチャIDを付け替える
  • メソッド:このテクスチャに対して操作を行う、現在値を取得する
  • コピー:新しいテクスチャIDを作成し、各種の設定をコピー元と同じものにする。ムーブコンストラクタのつもりで誤ってコピーコンストラクタを呼ぶのを防ぐため、コピーコンストラクタではなくメソッドとする
  • 代入:不可
  • デストラクタ:このテクスチャを破棄する

●コンテキスト

 OpenGLの一連の操作は、「コンテキスト」という単位で独立しています。コンテキストの切り替えはOS側が適切に行ってくれるため、ソースコード中で明示的にコンテキストを変更することはできません。
 このため、OpenGLを使う上でコンテキストを意識する必要は通常はないのですが、OOP的な考え方をするならば「現在のコンテキストオブジェクトのメソッドとして、GL関数がある」となるでしょうか?
 プログラム中で現在のコンテキスト以外の操作をすることはありませんが、複数のコンテキストが描画のために同じユーザー定義関数を呼ぶことは考えられます。関数側からコンテキストを区別できるよう、コンテキストを表すクラスも作ってしまうべきでしょう。

  • コンストラクタ/デストラクタ:環境依存(glutを使うならウィンドウと1:1対応させる、wglを使うならwglCreateContext()/wglDeleteContext()を呼ぶ)
  • コピー/代入:不可
  • メソッド:理想的には、OpenGLの全ての関数をメソッド化したい

以上の4つの機能を実装していく予定です。
それでは次回をお楽しみに。