【お知らせ】プログラミング記事の投稿はQiitaに移行しました。

Windowsネイティブ版

n7shi2009-10-01


モバイル関係でOpenGL ESの名前を目にすることが多くなりました。しかしWindowsネイティブの実装は登録が必要なものばかりで、フリーな実装が見当たりません。Vincent ESGLUT|ESのソースにはWin32の実装が含まれていますが、そのままではビルドできません。手直ししてVisual C++ 2008 Express Editionでビルドできるようにしました。x64もid:n7shi:20091005の方法によりExpressで開発しています。ソースとバイナリを置いておきます。

Vincent ESはソフトウェア描画で、ハードウェアアクセラレーションは使用していません。CreateDIBSection()で作成したバッファに描画して、eglSwapBuffers()でBitBlt()しています。
参考までに試行錯誤の経緯を記します。

謎のバイナリ

Windowsバイナリを探したところ次の記事を見付けました。

ここで言及されているように、サンプル付属のDLLは由来不明です。GLUT|ESにも同じようなDLLが付いてきますが、これもまた由来不明です。これでは安心して再配布ができません。

試しにGLUT|ESをビルドして付属のlibGLES_CM.dllのリンクを試みましたがエラーになります。当初Vincent ESのヘッダを使っていたのですが、ヘッダではstdcallでエクスポートが指示されているのに、DLLはcdeclになっているのが原因でした。cdeclに修正してリンクは成功しました。

しかしeglGetDisplay()がNULLを返すため初期化に失敗します。由来不明のWindowsバイナリだけでなく、CEバイナリでも同様に初期化に失敗します。Vincent ESのビルドを試したところ、eVC4で簡単にCEバイナリがビルドできました。自分でビルドしたlibGLES_CM.dllにGLUT|ESをリンクさせたところ、問題なく動きます。

どうやら付属のDLLはVincent ESと初期化の手順が異なるようです。ソースからビルドすればすんなり動くため、深く追求はせずに自分でビルドして使うことにしました。

Windows用の修正

Vincent ESにはWin32のプロジェクトは含まれていませんが、Win32のソースは含まれています。自分でプロジェクトを作成してビルドしてみました。x86ではARM関係(JIT)のソースは不要だろうと勝手に判断して削った所、まともに動きません。eVCのプロジェクトではx86 CEでもARM関係をそのままビルドしているため、同じようにすると動きました。ARM関係のコードは外せないようです。

自分でビルドしたlibGLES_CM.dllでGLUT|ESを動かすと、ウィンドウを無視して画面に直接描画します。ウィンドウを動かしても描画が連動しません。ソースを見ると、CEで全画面表示しているコードがそのままになっていました。サーフェスとウィンドウハンドルを関連付けして連動するようになりました。

描画がウィンドウのリサイズに連動しないのでWM_SIZEの処理を追加しました。しかしタイミングによっては描画がずれる問題が発生しました。試行錯誤した結果、内部バッファが16bitのDIBで確保されているため、横幅が奇数だとパディングが生じてずれることが判明しました。バッファの横幅を偶数に切り上げることで対処しました。

ちなみにGLUT|ES付属の謎バイナリではこのような問題はなく、描画やリサイズもきちんと実装されています。

CE用の修正

ついでにCEで気になる動きを修正しました。

GLUT|ESをそのまま使うと、全画面表示で[OK]キーも受け付けません。起動や終了が気軽ではありません。そのためタスクバーは隠さないようにして、[OK]で終了するように変更しました。

OpenGL関係のサンプルではキーボードで角度を調整するようなものが多いですが、アルファベットキーを押すとIMEが立ち上がってまともに操作できないため、起動時にIMEをオフにするようにしました。