chap05f from Ken Wakita on Vimeo.

この例は回転する立方体です.ここまでに学んだことを総動員します.

sb05fx.cpp (sb05f.vs,fs)


立方体の形状(Cube)は,VSの変数に静的に保存し,プロジェクション(Projection)と立方体の位置情報を表すモデルビュー行列(ModelView)は,Uniform変数を利用してGPUに送ります.シェーダはいずれも単純なものです.

例題Fのコード — sb05f.cpp (sb05f.vs,fs)

まず,立方体の形状を作らなくてはいけません.このために createCube という関数を用意しました. この関数のなかで,原点を中心にした単位立方体を作成しています.立方体を三角形に分割すると,各面が各々,二つの直角二等辺三角形から構成されます.すると全体で(6面×2つの三角形)=12個の三角形に分割することになります.それぞれの三角形の形状は3頂点の座標で定めますので,全体として頂点数は(6×2×3)個です.

今回の例題では視点(Camera)もプロジェクション(Projection)も原則的に変化させません.ただ,ウィンドウの大きさが変化したときだけ,プロジェクションを更新させます.SuperBibleのコードでは,毎回,レンダラーがプロジェクションを更新していましたが,それは無駄だと思います.私のコードでは,基本的にウィンドウの大きさが変化したときだけプロジェクションを再計算しています.

プロジェクション行列を更新したら,その都度,Uniformも更新しなくてはなりません.当初は,onResizeでそれをやろうとしていたのですが,うまくいきませんでした.Uniformを更新するためには,そのuniformを所有しているシェーダをまずuseProgramしておかなくてはいけないようです.このため,ちょっと汚ないような気もしますがupdateProjectionという論理値変数を用意して,必要に応じてレンダラーにuniformの更新を依頼するようにしています.

完成してみるとあたりまえのコードのような気もするのですが,作成途中ではなかなか画面表示が表れずに苦労しました.以下がはまりどころです.

  • シェーダのコンパイル・リンクエラーに気づいていなかった. → よく確認しましょう(自分).

  • OpenGL の関数でエラーが発生していないことをよく確認しましょう. → このために Check マクロを用意しました.

  • VAOとBAOが混乱していた. → 設計段階でよく考えておきましょう.

  • 立方体の形状がなんかおかしくて,遠近効果が逆転しているように見える. → 面の裏表の設定に注意しましょう.ぼくは裏面を塗っていました.