少々事情があって、しばらく3Dまわりのことをやることになった(あまり寄り道したくないのだけど、これは前々から決まっていたことなので仕方がない)。とりあえず、先月ちょいと眺めてみたopentkを実際にいじってみようと思い立った。とりあえずWebGL相当の機能がほしい。
OpenTKのバインディングは、それぞれ数千行単位で存在しているのだけど、どうやらこれらは自動生成されているようだ。少なくともOpenGL ESについてはそうらしい。WebGLはOpenGLES2.0のレベルで足りるので、その仕組みを探ってみた。ドキュメントがほとんど無いので、ジェネレータのソースから推測して動かしてみた部分が多い。
自動生成は、khronosが配布しているCのヘッダファイルを正規表現マッチで(書式決めうちで)解析して、その結果をいったんxmlにした上で、それをC#やC++に変換しているようだ。Converter.exeがCヘッダ解析とXML生成を行い、Bind.exeがXML解析とC#生成を行う。
Bind.exeはストレートに動作したのだけど、Converter.exeは引数をいろいろ指定してやらなければならない。実際には、ビルドして生成されたBinaries/OpenTK/Debugから Converter.exe -p=gl -v:2.0 ../../../Source/Converter/Headers/ES20/gl2ext.h ../../../Source/Converter/Headers/ES20/gl2.h > gl20.xml のように実行して生成する必要がある。生成されるのは Source/Bind/Specifications/ES20/signatures.xml のようなファイルだが、一応生成したものと既存のファイルが一致するかどうかを確認した方が良い(そして一致しない)。
OpenTKは、それをもとにenum, function (wrapper), delegate (DlllImport)といったメンバーを生成する。今回はDllImportが使えないので、ここに相当するコードを別のものとして書き換えたい。CSharpCodeBuilderに少し手を加えれば出来そうだけど、まずsignatures.xmlが適切に生成されていることが重要だ...と思って、ES20相当のファイルとWebGLの仕様を比較していて気がついた。
WebGLのメンバー名は割と変更されている...
たとえば、glGenBuffers()はWebGLRenderingContextではcreateBuffer()となっている。Javascriptにはポインタなど無いので、返値がそのままバッファオブジェクトになる。といった感じで、Javascript向けにいろいろ手を加えられているようだ。これはもはや別のAPIとして捉えた方が良さそうだ。
ふと気がついてES1.1とES2.0のそれぞれに対応するOpenTKのAPIを比較してみた。すると、どうやら1.1にしか無い関数などは2.0のバインディングには存在していないようだ。どうやらOpenTKは、互換性のために名前の違いを吸収するということはあまり行わず(overrides.xmlについてのみ行い)、対象バージョンに合ったAPIを自動生成するというアプローチを採っているようだ。それならば、WebGLについては、WebGLのAPIに合わせたAPIを自動生成すれば良さそうだ。
とりあえず今日わかったことはここまで。明日はもし出来たらAPI自動生成に挑戦してみようと思う。