« 実家の睡蓮2011 | トップページ | Delphi XE2のTCanvas »

2011年9月12日 (月)

Delphi XE2でOpenGL

9/1にRAD Studio XE2が届いて遊んでいます。元々は64bit化が気になってたんですが、FireMonkeyというクロスプラットフォーム向けのライブラリが面白くて、まず最初はこっちから手を付けています。

FireMonekyはまだバグがあり、いきなり実用アプリを作るのはおすすめしませんが、今から遊んでいればそのうちWindowsとMacOSX向けに簡単にアプリケーションが作れるようになるのではと期待してます。(iOS向けも作れますが、UIの違いが大きいのでどこまで実用的になるかは未知数)

FireMonkeyはもともとDelphi向けのDirectX用のシーングラフライブラリが元になっているらしくて3D機能が豊富です。しかし、個人的にはお仕着せのシーングラフライブラリを使うよりもDirectXなりOpenGLを生の状態で使いたいので、ちょっとサンプルを作ってみました。

続きでグダグダ説明を書きますが、サンプルソースを書いたので基本的にはこれを読んでもらえればOKです。
Download:SimpleSampleOpenGL_FMX.pas

<実行イメージ>
20110912_simplesampleopengl

・目的:
とりあえずMarbleCLAYの移植を目標として生のOpenGLをWin/Mac両方で使えるようにする

・構成:
OpenGLの初期化や基本機能だけを簡単なクラスでラップする。

Windows向けはOpenGLヘッダはDelphi添付のWinapi.OpenGL.pasを使う(OpenGL1.1相当かな)

OSX向けも添付のMacapi.OpenGL.pasを使う。(こちらは動的ロードに対応してて便利。何故同じレベルの実装にしないか謎)

※今回はサンプルなのでWin向けにも標準のOpenGL.pasを使いましたが、個人的には動的ロード対応のものを使っています。ただし出所が不明なので添付しませんでした。おいおいC向けのヘッダをpasに変換したものに変更予定(OpenGL4とかでも遊びたいので)。ちゃんとしたものができたら公開します。

・課題:

[Windows向け]の場合、フォームなりコントロールなりのHWNDさえ取得することができれば、あとは通常通りの初期化が可能。

フォームの場合は、Form.HandleからFMX.Platform.Win.FmxHandleToHWND()関数でHWNDを取得できます。

ただし、FMXのコントロールは以前のVCLとは違い、ウインドウハンドルをもちません。なので、フォームの一部だけをOpenGL表示にしたい等という場合にちょっと困ったことになりますが、これは別のポストにします。

さらに、Windows7(おそらくVistaでも)の場合、デフォルトでDirect2Dを使うようになるため、GDI+を使うようにします。(適当なinitialization節でGlobalUseDirect2D := false;)

[Mac向け]の場合、iOS周りでちょっと遊んだことがある程度でCocoaのことはほとんど無知な状態なのが第一の課題。

次に、OpenGLの操作をしようとすると、フォーム上のNSViewに触る必要が出てきます。そこでライブラリソースを読むことにしました(Delphiの利点としてライブラリソースの参照が非常に楽で気軽にできるというのがあります)。
しかし、FireMonkeyの場合プラットフォーム間の差異を吸収するクラスがすべてimplementation部に定義されていて、外部からNSViewを参照することができません。

Delphiの最近のバージョンではRTTIが強化されていて、クラスのローレベルの部分まで触ることができるようなので自力で色々やってみたものの、どうにもうまくいかなくてtwitterでつぶやいた所、

https://twitter.com/#!/zendenmushi/status/110705129044459521

「全力わはー」の@lynatanさんに実現方法を教えていただきました(感謝!) http://pastebin.com/RUXE339K

NSViewがとれれば後はレンダリングコンテキストに対してsetView()をすることでViewとOpenGLを結びつけることができます。

(OpenGLの初期化自体はFireMonkeyのやりかたを参考にしたりCocoa関連の資料を見れば比較的簡単にできます。基本はPixelFormat設定とNSOpenGLContextの作成なのでWinとそう大差ありません)

あとは普通にOpenGLのAPIを呼び出すことで描画ができるようになったんですが、フォームのリサイズ時にOpenGLの原点が変わらない(フォームの左下に追従しない)という問題が出ました。

色々調べたところ、フォームのリサイズ時にNSOpenGLContext.update()を呼ぶ必要があったようです。

・まとめ:
とりあえず上記の方法で、フォーム全体をOpenGL描画することはできるようになりました。

ちゃんとしたアプリケーションを作るためにはフォームの一部だけをOpenGL描画にしたいところですが、前述のとおりFireMonkeyではコントロールにウインドウハンドルが無いため一筋縄ではいきません。

WindowsXPであれば、シングルバッファ構成にしてglScissor()を使うことでフォームの一部だけを更新するようにできましたが、Windows7では無理のようです。

今のところOpenGL用のフォームそのものをメインフォームに埋め込むことで回避していますが、泥くさすぎるコードのため、今回のサンプルには含めませんでした。良い方法がわかればまた投稿します。

|

« 実家の睡蓮2011 | トップページ | Delphi XE2のTCanvas »

Delphi」カテゴリの記事

FireMonkey/Delphi XE2」カテゴリの記事

OpenGL」カテゴリの記事

コメント

Great goods from you, man. Delphi XE2でOpenGL: 生き物コーディング I've understand your stuff previous to and you're just too wonderful. I actually like what you have acquired here, certainly like what you are stating and the way in which you say it. You make it entertaining and you still take care of to keep it wise. I cant wait to read far more from you. This is really a terrific Delphi XE2でOpenGL: 生き物コーディング informations.

投稿: minecraft skins | 2012年1月17日 (火) 23時35分

コメントを書く



(ウェブ上には掲載しません)




トラックバック


この記事へのトラックバック一覧です: Delphi XE2でOpenGL:

« 実家の睡蓮2011 | トップページ | Delphi XE2のTCanvas »