OpenGLSimpleShaderAdapter

やあ子供たち。
以前VertexAttribArrayHelper(VAAH)というものを作りました。
これはつまり、glVertexAttribPointer()やglBufferDate()など、何かと解り難いOpenGLAPIの呼び出しをラップして、固定パイプラインと呼ばれる、
API(glBegin(), glVertex3f(), glEnd())の使い勝手を再現しようとしたものであり、旧APIに慣れた身には非常に便利なものではあったが、

しかし、その名にそぐわないことに、対応している頂点アトリビュートが固定で、使用可能なVertexAttributeは、Position, Normal, Color, TexUV のみであった。それ以外の、例えばTangentVectorだとか、Binormalだとか、あるいはマルチテクスチャー時に必要となってくるはずの第2、第3のTexUV値なども頂点バッファに詰め込みたいといった場合、残念ながらVAAHそのものを書き換えなくてはならなかった。

それもまあよかったのだが、そういうのをきっかけとして、また一歩考えを進めてみると、この時代のOpenGLで言う「描画」とは、各シェーダープログラムの記述内容を具現化することのみ、という流れであることに気付いて見れば、VAAHのようなものは、もしかするとシェーダーの読み込み・管理を行う、処理単位と融合された姿が理想なのではないかと考えるに至ったわけである。

なんだか俺はお化けクラスのようなものを作ろうとしているのだろうかと思ってしまうが、概念はシンプルでそれはつまり上述の、

  • シェーダープログラムを解析し(全入力アトリビュートの位置取得し)
  • そこに、必要なだけの頂点バッファ(各入力アトリビュートに対し)
    の内容を流し込み
  • 描画する

という機能をまとめてラップした、いわば「シェーダー実行環境」「シェーダー機能一切合切のラッパー的なもの」名づけようものなら「シェーダーヘルパー」「シェーダーアダプター」を作りたいと思うに至ったわけでありました。

OpenGLのプログラムは本当に煩雑化しやすいです。
ステートマシンである上に内部構造が公開されていないので、BindやらActiveやらいろんなAPIをみんな訳も分からず呼ばざるを得ない状況です。glが頭につくすべてのAPIって全部グローバル関数ですよね。名前空間すらないです。ステートをグローバル変数と読み替えるなら、これは
グローバル変数の状態を常に気にしなくてはならない、グローバル関数が集まってできたAPI体系」、
これがOpenGLです。
こわいですね。各APIに与える引数とは別に、グローバルなステートが常にその動作に何らかの影響を与える可能性があるわけです。よっぽど好きでなければ使いたくはならないはずですこんなライブラリ。改めて冷静に考えてみても、グローバル関数のみからなる、C言語ライクなライブラリは世にたくさんありますが、グローバル変数の状態を常に前提とするような最低な造りはOpenGLくらいしか思いつかないです。
はい、昔からOpenGL大好きでしたが、こう書いてみると本当は大嫌いだったのかも知れません。いえいえ、もちろんOpenGLの出力結果は大好きなのです。しかし、APIの体系は本当に大嫌いです。
次にシェーダー、テクスチャーまわりでまずいと思うことを書きます。
glUniform()を使えばどこからでも任意のシェーダーのパラメータを変更できてしまう。これがまずいけない。これに対する対策を考えた内容がこうです。
「特定のシェーダーパラメータへの一切のglUniform()呼び出しは、シェーダーアダプターが行うべきである。」
そう、例えば赤だったものを青にしたいなどの色情報変更に際して、シェーダーのパラメータの変更がしたければ、その旨シェーダーヘルパーに依頼するようにし、決して勝手なglUniform()呼び出しはしない。
同様に、
「特定のシェーダーが使うテクスチャー情報のGPUへの登録も、シェーダーアダプターが行うべき。」
テクスチャーというものは、フラグメントシェーダーの中で、samplerという変数に抽象化されるので、このsamplerのシンボルと、テクスチャ画像情報とを結びつけることを、シェーダーアダプターが受け持つというしくみにして、その辺はもう全部シェーダーアダプターの中で閉じてしまうのである。
いかがだろうか。これでわけのわからない場所に、glUniform()やら、glActiveTexture()やら、glBindTexture()、glTexImage2d()などが現れ、混乱させられる事態を、回避できる。
素晴らしきシェーダーアダプター。
さてその実装を見てみよう。
(続く。(続かないかも知れないが))